@@ -1,147 +0,0 @@
|
||||
# PyRoboLearn
|
||||
|
||||
This repository contains the code for the *PyRoboLearn* (PRL) framework: a Python framework for Robot Learning.
|
||||
This framework revolves mainly around 7 axes: simulators, worlds, robots, interfaces, learning tasks (= environment and policy), learning models, and learning algorithms.
|
||||
|
||||
**Warning**: The development of this framework is ongoing, and thus some substantial changes might occur. Sorry for the inconvenience.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
The framework has been tested with Python 2.7 and Ubuntu 16.04 and 18.04. We also tested parts of it with Python 3.5 on Ubuntu 16.04 and so far so good, but there might be some errors that escaped my attention.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Docker
|
||||
At the moment the docker is a self contained Ubuntu image with all the libraries installed. When launched we have access to a Python3.6 interpreter and we can import pyrobolearn directly.
|
||||
In the future, ROS may be splitted in another container and linked to this one.
|
||||
|
||||
1. Install Docker and nvidia-docker
|
||||
```bash
|
||||
$ sudo apt-get update
|
||||
$ sudo apt install apt-transport-https ca-certificates curl software-properties-common
|
||||
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable # you should replace bionic by your version
|
||||
$ sudo apt update
|
||||
$ sudo apt install docker-ce
|
||||
$ sudo systemctl status docker # check that docker is active
|
||||
```
|
||||
2. Build the image
|
||||
```bash
|
||||
$ docker build -t pyrobolearn .
|
||||
```
|
||||
3. Launch
|
||||
|
||||
|
||||
You can now start the python interpreter with every library already installed
|
||||
|
||||
```bash
|
||||
$ docker run -p 11311:11311 -v $PWD/dev:/pyrobolearn/dev/:rw -ti pyrobolearn python3
|
||||
```
|
||||
|
||||
To open an interactive terminal in the docker image use:
|
||||
|
||||
```bash
|
||||
$ docker run -p 11311:11311 -v $PWD/dev:/pyrobolearn/dev/:rw -ti pyrobolearn /bin/bash
|
||||
```
|
||||
|
||||
4. nvidia-docker
|
||||
if the GPU is not recognized in the interpreter, you can install nvidia-docker
|
||||
|
||||
```bash
|
||||
$ curl -sL https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
|
||||
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
|
||||
$ curl -sL https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install nvidia-docker2
|
||||
sudo pkill -SIGHUP dockerd
|
||||
```
|
||||
|
||||
And use:
|
||||
```bash
|
||||
$ nvidia-docker run -p 11311:11311 -v $PWD/dev:/pyrobolearn/dev/:rw -ti pyrobolearn
|
||||
```
|
||||
|
||||
### Ubuntu
|
||||
|
||||
1. First download the `pip` Python package manager and create a virtual environment for Python as described in the following link: https://packaging.python.org/guides/installing-using-pip-and-virtualenv/
|
||||
On Ubuntu, you can install `pip` and `virtualenv` by typing in the terminal:
|
||||
|
||||
- In Python 2.7:
|
||||
```bash
|
||||
sudo apt install python-pip
|
||||
sudo pip install virtualenv
|
||||
```
|
||||
|
||||
- In Python 3.5:
|
||||
```bash
|
||||
sudo apt install python3-pip
|
||||
sudo pip install virtualenv
|
||||
```
|
||||
|
||||
You can then create the virtual environment by typing:
|
||||
```bash
|
||||
virtualenv -p /usr/bin/python<version> <virtualenv_name>
|
||||
# activate the virtual environment
|
||||
source <virtualenv_name>/bin/activate
|
||||
```
|
||||
where `<version>` is the python version you want to use (select between `2.7` or `3.5`), and `<virtualenv_name>` is a name of your choice for the virtual environment. For instance, it can be `py2.7` or `py3.5`.
|
||||
|
||||
To deactivate the virtual environment, just type:
|
||||
```bash
|
||||
deactivate
|
||||
```
|
||||
|
||||
2. clone this repository and install the requirements by executing the setup.py
|
||||
|
||||
In Python 2.7:
|
||||
```bash
|
||||
git clone https://github.com/robotlearn/pyrobolearn
|
||||
cd pyrobolearn
|
||||
pip install numpy cython
|
||||
pip install http://github.com/cornellius-gp/gpytorch/archive/alpha.zip # this is for Python 2.7
|
||||
pip install -e . # this will install pyrobolearn as well as the required packages (so no need for: pip install -r requirements.txt)
|
||||
```
|
||||
|
||||
In Python 3.5:
|
||||
```bash
|
||||
git clone https://github.com/robotlearn/pyrobolearn
|
||||
cd pyrobolearn
|
||||
pip install numpy cython
|
||||
pip install gpytorch # this is for Python 3.5
|
||||
pip install -e . # this will install pyrobolearn as well as the required packages (so no need for: pip install -r requirements.txt)
|
||||
```
|
||||
|
||||
Depending on your computer configuration and the python version you use, you might need to install also the following packages through `apt-get`:
|
||||
```bash
|
||||
sudo apt install python-tk # if python 2.7
|
||||
sudo apt install python3-tk # if python 3.5
|
||||
```
|
||||
|
||||
## How to use it?
|
||||
|
||||
Check the `README.md` file in the `examples` folder.
|
||||
|
||||
## Citation
|
||||
|
||||
```
|
||||
@misc{delhaisse2019pyrobolearn,
|
||||
author = {Delhaisse, Brian and Xin, Songyan and Rozo, Leonel, and Caldwell, Darwin},
|
||||
title = {PyRoboLearn: A Python Framework for Robot Learning Practitioners},
|
||||
howpublished = {\url{https://github.com/robotlearn/pyrobolearn}},
|
||||
year=2019,
|
||||
}
|
||||
```
|
||||
|
||||
If you use a specific learning model, algorithm, robot, controller, and so on, please cite the corresponding paper. The reference(s) can usually be found in the class documentation (at the end), and sometimes in the README file in the corresponding folder.
|
||||
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Currently, we mainly use the PyBullet simulator.
|
||||
- *PyBullet, a Python module for physics simulation for games, robotics and machine learning*,
|
||||
Erwin Coumans and Yunfei Bai, 2016-2019
|
||||
- references for each robot, model, and others can be found in the corresponding class documentation
|
||||
- Locomotion controllers were provided by Songyan Xin (see `pyrobolearn/controllers/locomotion`).
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
PyRoboLearn
|
||||
===========
|
||||
|
||||
This repository contains the code for the *PyRoboLearn* (PRL) framework: a Python framework for Robot Learning.
|
||||
This framework revolves mainly around 7 axes: simulators, worlds, robots, interfaces, learning tasks (= environment and policy), learning models, and learning algorithms.
|
||||
|
||||
**Warning**: The development of this framework is ongoing, and thus some substantial changes might occur. Sorry for the inconvenience.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
The framework has been tested with Python 2.7 and Ubuntu 16.04 and 18.04. We also tested parts of it with Python 3.5 on Ubuntu 16.04 and so far so good, but there might be some errors that escaped my attention.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Docker
|
||||
~~~~~~
|
||||
|
||||
At the moment the docker is a self contained Ubuntu image with all the libraries installed. When launched we have access to a Python3.6 interpreter and we can import pyrobolearn directly.
|
||||
In the future, ROS may be splitted in another container and linked to this one.
|
||||
|
||||
1. Install Docker and nvidia-docker
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt install apt-transport-https ca-certificates curl software-properties-common
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable # you should replace bionic by your version
|
||||
sudo apt update
|
||||
sudo apt install docker-ce
|
||||
sudo systemctl status docker # check that docker is active
|
||||
|
||||
2. Build the image
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker build -t pyrobolearn .
|
||||
|
||||
|
||||
3. Launch
|
||||
|
||||
|
||||
You can now start the python interpreter with every library already installed
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker run -p 11311:11311 -v $PWD/dev:/pyrobolearn/dev/:rw -ti pyrobolearn python3
|
||||
|
||||
|
||||
To open an interactive terminal in the docker image use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker run -p 11311:11311 -v $PWD/dev:/pyrobolearn/dev/:rw -ti pyrobolearn /bin/bash
|
||||
|
||||
|
||||
4. nvidia-docker
|
||||
if the GPU is not recognized in the interpreter, you can install nvidia-docker
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -sL https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
|
||||
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
|
||||
curl -sL https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install nvidia-docker2
|
||||
sudo pkill -SIGHUP dockerd
|
||||
|
||||
And use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
nvidia-docker run -p 11311:11311 -v $PWD/dev:/pyrobolearn/dev/:rw -ti pyrobolearn
|
||||
|
||||
|
||||
Ubuntu
|
||||
~~~~~~
|
||||
|
||||
1. First download the ``pip`` Python package manager and create a virtual environment for Python as described in the following link: https://packaging.python.org/guides/installing-using-pip-and-virtualenv/
|
||||
On Ubuntu, you can install ``pip`` and ``virtualenv`` by typing in the terminal:
|
||||
|
||||
- In Python 2.7:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt install python-pip
|
||||
sudo pip install virtualenv
|
||||
|
||||
- In Python 3.5:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt install python3-pip
|
||||
sudo pip install virtualenv
|
||||
|
||||
You can then create the virtual environment by typing:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
virtualenv -p /usr/bin/python<version> <virtualenv_name>
|
||||
# activate the virtual environment
|
||||
source <virtualenv_name>/bin/activate
|
||||
|
||||
where ``<version>`` is the python version you want to use (select between ``2.7`` or ``3.5``), and ``<virtualenv_name>`` is a name of your choice for the virtual environment. For instance, it can be ``py2.7`` or ``py3.5``.
|
||||
|
||||
To deactivate the virtual environment, just type:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
deactivate
|
||||
|
||||
2. clone this repository and install the requirements by executing the ``setup.py``
|
||||
|
||||
In Python 2.7:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/robotlearn/pyrobolearn
|
||||
cd pyrobolearn
|
||||
pip install numpy cython
|
||||
pip install http://github.com/cornellius-gp/gpytorch/archive/alpha.zip # this is for Python 2.7
|
||||
pip install -e . # this will install pyrobolearn as well as the required packages (so no need for: pip install -r requirements.txt)
|
||||
|
||||
In Python 3.5:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/robotlearn/pyrobolearn
|
||||
cd pyrobolearn
|
||||
pip install numpy cython
|
||||
pip install gpytorch # this is for Python 3.5
|
||||
pip install -e . # this will install pyrobolearn as well as the required packages (so no need for: pip install -r requirements.txt)
|
||||
|
||||
Depending on your computer configuration and the python version you use, you might need to install also the following packages through ``apt-get``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt install python-tk # if python 2.7
|
||||
sudo apt install python3-tk # if python 3.5
|
||||
|
||||
|
||||
How to use it?
|
||||
--------------
|
||||
|
||||
Check the ``README.rst`` file in the ``examples`` folder.
|
||||
|
||||
Citation
|
||||
--------
|
||||
|
||||
.. code-block:: latex
|
||||
|
||||
@misc{delhaisse2019pyrobolearn,
|
||||
author = {Delhaisse, Brian and Xin, Songyan and Rozo, Leonel, and Caldwell, Darwin},
|
||||
title = {PyRoboLearn: A Python Framework for Robot Learning Practitioners},
|
||||
howpublished = {\url{https://github.com/robotlearn/pyrobolearn}},
|
||||
year=2019,
|
||||
}
|
||||
|
||||
|
||||
If you use a specific learning model, algorithm, robot, controller, and so on, please cite the corresponding paper. The reference(s) can usually be found in the class documentation (at the end), and sometimes in the README file in the corresponding folder.
|
||||
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
|
||||
Currently, we mainly use the PyBullet simulator.
|
||||
|
||||
- *PyBullet, a Python module for physics simulation for games, robotics and machine learning*, Erwin Coumans and Yunfei Bai, 2016-2019
|
||||
- references for each robot, model, and others can be found in the corresponding class documentation
|
||||
- Locomotion controllers were provided by Songyan Xin (see ``pyrobolearn/controllers/locomotion``)
|
||||
@@ -0,0 +1,19 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# . venv/bin/activate
|
||||
|
||||
rm -Rf build
|
||||
rm -Rf source/docstring
|
||||
|
||||
sphinx-apidoc -f -o source/docstring/ ../pyrobolearn
|
||||
make html
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
Actions
|
||||
=======
|
||||
|
||||
In PRL, every concept is modelized as a class. This is also true for actions which are used by the policies.
|
||||
|
||||
.. figure:: ../figures/environment.png
|
||||
:alt: environment
|
||||
:align: center
|
||||
|
||||
The agent-environment interaction
|
||||
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
|
||||
How to use a particular action?
|
||||
------------------------------
|
||||
|
||||
example of actions with robot
|
||||
|
||||
|
||||
How to create your own action?
|
||||
------------------------------
|
||||
|
||||
|
||||
FAQs
|
||||
----
|
||||
@@ -0,0 +1,2 @@
|
||||
Algorithms
|
||||
==========
|
||||
@@ -0,0 +1,14 @@
|
||||
Approximators
|
||||
=============
|
||||
|
||||
An ``Approximator`` accepts as inputs the ``State``, ``Action``, and learning ``Model``, and connects them.
|
||||
Approximators are used by other classes in the PRL framework.
|
||||
|
||||
|
||||
How to use an approximator?
|
||||
---------------------------
|
||||
|
||||
|
||||
How to create your own approximator?
|
||||
------------------------------------
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('../..'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = u'PyRoboLearn'
|
||||
copyright = u'2019, Brian Delhaisse'
|
||||
author = u'Brian Delhaisse'
|
||||
|
||||
# The short X.Y version
|
||||
version = u''
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'0.0.1'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.githubpages',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = None
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme' # 'alabaster'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'PyRoboLearndoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'PyRoboLearn.tex', u'PyRoboLearn Documentation',
|
||||
u'Brian Delhaisse', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'pyrobolearn', u'PyRoboLearn Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'PyRoboLearn', u'PyRoboLearn Documentation',
|
||||
author, 'PyRoboLearn', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#
|
||||
# epub_uid = ''
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
|
||||
# -- Extension configuration -------------------------------------------------
|
||||
|
||||
# -- Options for intersphinx extension ---------------------------------------
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'https://docs.python.org/': None}
|
||||
@@ -0,0 +1,157 @@
|
||||
Environments
|
||||
============
|
||||
|
||||
The environment is one of the main concept in imitation and reinforcement learning as defined in the following figures (inspired by [1]_):
|
||||
|
||||
.. figure:: ../figures/environment.png
|
||||
:alt: environment
|
||||
:align: center
|
||||
|
||||
The agent-environment interaction
|
||||
|
||||
|
||||
The environment is notably responsible to perform a step in the world, compute the next state, compute the rewards, and others.
|
||||
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
In PRL, the environment is an abstraction layer class that regroups:
|
||||
|
||||
- the world; an instance of ``World`` which will be used to perform a step in the world (simulator). This is called at each step performed by the environment.
|
||||
- the states: an instance of ``State`` (or a list of them). The states are updated at each time step by the environment.
|
||||
- the rewards (optional): an instance of ``Reward`` (or a list of them). It is optional because some environments like in imitation learning does not require a reward function. The reward functions are computed at each time step.
|
||||
- the terminal conditions (optional): an instance of ``TerminalCondition`` (or a list of them) that checks at each time step if the goal of the environment has been achieved. A ``TerminalCondition`` also details if the environment ended with a success or failure.
|
||||
- the initial state generators (optional): an instance of ``StateGenerator`` (or a list of them) which are called to generate the initial states each time the environment is reset.
|
||||
- the physics randomizers (optional): an instance of ``PhysicsRandomizer`` (or a list of them) to randomize the physical properties of bodies in the simulator, or the simulator itself, each time the environment is reset.
|
||||
- the actions (optional): an instance of ``Action`` (or a list of them). The actions are not used nor updated by the environment. This is left to the ``Policy`` or ``Controller``.
|
||||
|
||||
|
||||
By favoring `composition over inheritance <https://en.wikipedia.org/wiki/Composition_over_inheritance>`_ for the environment class, we improve the flexibility of the framework and the reuse of different modules. This leads ultimately to less code duplication, and ease the process of creating environments.
|
||||
|
||||
|
||||
.. figure:: ../UML/environment.png
|
||||
:alt: UML diagram for Environment
|
||||
:align: center
|
||||
|
||||
UML diagram for environment
|
||||
|
||||
|
||||
How to use an environment?
|
||||
--------------------------
|
||||
|
||||
Let's assume that you have an environment where you have a manipulator, and the goal is to reach an object (such as a cube) on a table.
|
||||
|
||||
Here is a short snippet showing the basic usage of an environment:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
# define the simulator and world (and load what you want in it)
|
||||
sim = ...
|
||||
world = ...
|
||||
robot = ...
|
||||
|
||||
# define state, action, and reward (and possibly action)
|
||||
state = ...
|
||||
action = ...
|
||||
reward = ...
|
||||
|
||||
# you can give the reward function to your RL environment
|
||||
# which will use it when calling `env.step()`.
|
||||
env = prl.envs.Env(world, state, reward)
|
||||
|
||||
# like in OpenAI gym environments, you can reset and step in the environment
|
||||
obs = env.reset()
|
||||
for t in count():
|
||||
obs, rew, done, info = env.step()
|
||||
|
||||
|
||||
Few notes regarding the code above:
|
||||
|
||||
- the ``action`` can also be given to the environment but it won't be called by the environment. This is carried out by the policy(ies)/agent(s). The main reason why you can give an action to an environment is when later you will create your own environment class (that inherits from ``prl.envs.Env``), you will be able to get the states and actions for your policies in the following way:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
# define your environment
|
||||
class MyEnv(prl.envs.Env):
|
||||
...
|
||||
|
||||
# create the environment and provide possible arguments
|
||||
env = MyEnv(args)
|
||||
|
||||
# get states and actions from your environment
|
||||
states, actions = env.states, env.actions
|
||||
|
||||
# create policy
|
||||
policy = Policy(states, actions)
|
||||
|
||||
- the observation ``obs`` is a list of arrays that are returned by the environment. This is a bit different from what it is usually returned by gym environments (which is an array). The reason is that the states returned by the environment might have different dimensions (e.g. joint positions = 1D array, camera = 2D/3D array, etc) so you can not return one array.
|
||||
- You can easily update the state, reward function, world, and other modules that are given to environment. This results in less code duplication and greater flexibility.
|
||||
|
||||
Few more examples can be found in `pyrobolearn/examples/environments <https://github.com/robotlearn/pyrobolearn/tree/master/examples/environments/>`_.
|
||||
|
||||
If you would like other people to use your environment, implement your environment class like described in the section below.
|
||||
|
||||
|
||||
How to create my own environment?
|
||||
---------------------------------
|
||||
|
||||
Using the same example as the section above REF.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
class MyEnv(Env): # inherit from the PRL Env class
|
||||
"""Description"""
|
||||
|
||||
# specify what the user is allowed to change in your environment by providing optional inputs
|
||||
# in this case, let's say he is allowed to change the manipulator: use Franka Panda instead of Kuka
|
||||
def __init__(self, manipulator=None, ...):
|
||||
# initialize the world as you would like by loading different objects in it
|
||||
world = ...
|
||||
...
|
||||
|
||||
# make sure the given manipulator is valid
|
||||
if manipulator is None:
|
||||
manipulator = world.load_robot('kuka_iiwa', ...)
|
||||
if not isinstance(manipulator, prl.robots.Manipulator):
|
||||
raise TypeError("Expecting a manipulator, instead got: {}".format(type(manipulator)))
|
||||
|
||||
# create the states
|
||||
states = state1(manipulator) + ...
|
||||
|
||||
# create the reward
|
||||
reward = ...
|
||||
|
||||
# other stuffs
|
||||
...
|
||||
|
||||
# call the parent's constructor
|
||||
super(MyEnv, self).__init__(world, states, rewards, ...)
|
||||
|
||||
|
||||
You normally don't have to implement anything else (like the ``step``, ``reset``, and other functions are automatically implemented based on what you provided to the parent's constructor).
|
||||
|
||||
|
||||
What are the differences with the OpenAI gym's environments?
|
||||
------------------------------------------------------------
|
||||
|
||||
To better depict the differences, let's consider an environment which contains a quadruped robot and the goal is that it learns to walk. Usually, as it can be seen on multiple repositories, people would inherit from the gym ``Env`` class and call it something similar to ``QuadrupedFlatTerrainWalkEnv(Env)``. Inside of ``step`` function, they would compute the next states and rewards. Now suppose, you would like to change ...
|
||||
|
||||
In our framework, the ``world``, ``states``, and ``rewards`` are given to the PRL ``Env`` class. This means that if you would like to change the world, reward function, or states you can do it outside the function.
|
||||
|
||||
- Actions
|
||||
|
||||
Having said that, we tried to make PRL compatible with OpenAI gym at the exception that the returned state is not a array but a list of arrays.
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [1] "Reinforcement Learning: An Introduction", Sutton and Barto, 1998
|
||||
@@ -0,0 +1,2 @@
|
||||
.. include:: ../../examples/README.rst
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
FAQs
|
||||
====
|
||||
|
||||
* How to add a completely new component, for instance, a state estimator or navigation (SLAM) module? There are multiple steps: 1. you have to divide your code into submodules that are minimal, do not depend on various pieces of code. 2. Compositonality 3. Flexibility: if I want to change something how easy is it?
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
.. PyRoboLearn documentation master file, created by
|
||||
sphinx-quickstart on Thu Jun 20 20:28:11 2019.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root toctree directive.
|
||||
|
||||
Welcome to PyRoboLearn's documentation!
|
||||
=======================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Introduction
|
||||
|
||||
readme
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:caption: Installation
|
||||
|
||||
installation
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
:caption: PyRoboLearn
|
||||
|
||||
pyrobolearn
|
||||
simulators
|
||||
worlds
|
||||
robots
|
||||
interfaces
|
||||
states
|
||||
actions
|
||||
rewards
|
||||
environments
|
||||
models
|
||||
approximators
|
||||
algorithms
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Examples
|
||||
|
||||
examples
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:caption: Package Reference
|
||||
|
||||
docstring/modules
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Index
|
||||
|
||||
indices
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
Indices and tables
|
||||
==================
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
There are 2 ways to install the PyRoboLearn framework.
|
||||
|
||||
1. via :ref:`Docker`
|
||||
2. using a :ref:`Virtual Environment`
|
||||
|
||||
|
||||
.. _Docker:
|
||||
|
||||
Docker
|
||||
-------
|
||||
|
||||
At the moment the docker is a self contained Ubuntu image with all the libraries installed. When launched we have access to a Python3.6 interpreter and we can import pyrobolearn directly.
|
||||
In the future, ROS may be splitted in another container and linked to this one.
|
||||
|
||||
1. Install Docker and nvidia-docker
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt install apt-transport-https ca-certificates curl software-properties-common
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable # you should replace bionic by your version
|
||||
sudo apt update
|
||||
sudo apt install docker-ce
|
||||
sudo systemctl status docker # check that docker is active
|
||||
|
||||
2. Build the image
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker build -t pyrobolearn .
|
||||
|
||||
3. You can now start the python interpreter with every library already installed
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker run -p 11311:11311 -v catkin_ws:/pyrobolearn/catkin_ws/ -ti pyrobolearn python3
|
||||
|
||||
|
||||
To open an interactive terminal in the docker image use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker run -p 11311:11311 -v catkin_ws:/pyrobolearn/catkin_ws/ -ti pyrobolearn /bin/bash
|
||||
|
||||
|
||||
4. If the GPU is not recognized in the interpreter, you can install ``nvidia-docker``
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -sL https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
|
||||
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
|
||||
curl -sL https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install nvidia-docker2
|
||||
sudo pkill -SIGHUP dockerd
|
||||
|
||||
And use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
nvidia-docker run -p 11311:11311 -v catkin_ws:/pyrobolearn/catkin_ws/ -ti pyrobolearn
|
||||
|
||||
|
||||
.. _Virtual Environment:
|
||||
|
||||
Virtual Environment
|
||||
-------------------
|
||||
|
||||
0. Prerequisites: install the following packages on your Ubuntu system
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt-get install cmake gfortran
|
||||
|
||||
|
||||
1. First download the ``pip`` Python package manager and create a virtual environment for Python as described in the following link: https://packaging.python.org/guides/installing-using-pip-and-virtualenv/
|
||||
|
||||
On Ubuntu, you can install ``pip`` and ``virtualenv`` by typing in the terminal:
|
||||
|
||||
- In Python 2.7:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt install python-pip
|
||||
sudo pip install virtualenv
|
||||
|
||||
- In Python 3.5:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt install python3-pip
|
||||
sudo pip install virtualenv
|
||||
|
||||
|
||||
You can then create the virtual environment by typing:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
virtualenv -p /usr/bin/python<version> <virtualenv_name>
|
||||
# activate the virtual environment
|
||||
source <virtualenv_name>/bin/activate
|
||||
|
||||
where ``<version>`` is the python version you want to use (select between ``2.7`` or ``3.5``), and ``<virtualenv_name>`` is a name of your choice for the virtual environment. For instance, it can be ``py2.7`` or ``py3.5``.
|
||||
|
||||
To deactivate the virtual environment, just type:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
deactivate
|
||||
|
||||
|
||||
2. clone this repository and install the requirements by executing the ``setup.py``
|
||||
|
||||
In Python 2.7:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/robotlearn/pyrobolearn
|
||||
cd pyrobolearn
|
||||
pip install numpy cython
|
||||
pip install http://github.com/cornellius-gp/gpytorch/archive/alpha.zip # this is for Python 2.7
|
||||
pip install -e . # this will install pyrobolearn as well as the required packages (so no need for: pip install -r requirements.txt)
|
||||
|
||||
In Python 3.5:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/robotlearn/pyrobolearn
|
||||
cd pyrobolearn
|
||||
pip install numpy cython
|
||||
pip install gpytorch # this is for Python 3.5
|
||||
pip install -e . # this will install pyrobolearn as well as the required packages (so no need for: pip install -r requirements.txt)
|
||||
|
||||
|
||||
Depending on your computer configuration and the python version you use, you might need to install also the following packages through ``apt-get``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt install python-tk # if python 2.7
|
||||
sudo apt install python3-tk # if python 3.5
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
Interfaces and Bridges
|
||||
======================
|
||||
|
||||
**I/O interfaces** allows you to receive/send data from/to different devices. Interfaces are divided into 3 categories, ``InputInterface`` which can only receive data from a particular device and save it in memory, ``OutputInterface`` which can only send data given by PRL to the interface, and ``InputOutputInterface`` which allows you to receive and send data. Interfaces include for instance webcam, speaker, mouse, keyboard, game controller, and so on.
|
||||
|
||||
To avoid a direct coupling with the interface and an element in PRL such as a robot, **bridges** are introduced. Bridges makes the connection between an interface and an element in PRL (like a robot, an object in the world, the world itself, the world camera, etc). For instance, you could have a game controller and when moving one of its joystick forward, you would like for a quadcopter to take off while for a wheeled robot to move forward instead. For both examples, the values returned by the joystick is the same but you would like to have different behaviors depending on the type of robots. It might be even the case that someone would like to map the game controller events in a different way that you did. This is exactly the raison d'être of such bridges; to map an interface with an element in PRL. Different bridges can be implemented for the same interface as the user sees fit.
|
||||
|
||||
Available interfaces in PRL include:
|
||||
|
||||
- camera: webcam, asus_xtion, kinect, openpose
|
||||
- controllers: mouse+keyboard, spacemouse, playstation, xbox
|
||||
- speech: recognizer, translator, and synthesizer
|
||||
- VR: Oculus (through Windows)
|
||||
|
||||
They are available in `pyrobolearn/tools/interfaces/ <https://github.com/robotlearn/pyrobolearn/tree/master/pyrobolearn/tools/interfaces>`_ folder while bridges are available in the `pyrobolearn/tools/bridges/ <https://github.com/robotlearn/pyrobolearn/tree/master/pyrobolearn/tools/bridges>`_ folder.
|
||||
|
||||
|
||||
How to use an interface/bridge in PRL?
|
||||
--------------------------------------
|
||||
|
||||
The following snippet show how to use the space mouse interface.
|
||||
|
||||
|
||||
|
||||
|
||||
You can check for more examples in the `examples/interfaces <https://github.com/robotlearn/pyrobolearn/tree/master/examples/interfaces>`_ folder.
|
||||
|
||||
|
||||
|
||||
How to create your own interface/bridge?
|
||||
----------------------------------------
|
||||
|
||||
Let's say that you have a new interface, for instance, an EMG sensor that measures the electrical activity of muscles, and you would like based on the sensed values makes a robot behave in a certain way. For instance, you would like the robot to be more stiff (see teleimpedance for more info).
|
||||
|
||||
- In order to create your interface, you will have to inherit one of the following interfaces: ``InputInterface``, ``OutputInterface``, ``InputOutputInterface`` based on the type of device you have. In our case, we have an EMG sensor which provides the sensed values as *inputs* to PRL, thus we will inherit from ``InputInterface``.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
# please add the word `Interface` at the end of your class so we can based on its name alone
|
||||
# knows it is an interface.
|
||||
class EMGInterface(InputInterface):
|
||||
"""
|
||||
Description
|
||||
"""
|
||||
|
||||
def __init__(self, use_thread=False, sleep_dt=0, verbose=False, *args, **kwargs):
|
||||
# initialize your variables/attributes
|
||||
...
|
||||
|
||||
# call at the end the parent constructor
|
||||
super(EMGInterface, self).__init__(self, use_thread, sleep_dt, verbose)
|
||||
|
||||
def run(self):
|
||||
"""main method to implement. This method is automatically called when using threads, and you
|
||||
have to call it when you are not using threads."""
|
||||
# get the last sensed data and save it in one of the attributes of this class
|
||||
...
|
||||
|
||||
- Now, let's create a bridge that connects the above interface with a manipulator robot.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
# please add the word `Interface` at the end of your class so we can based on its name alone
|
||||
# knows it is an interface.
|
||||
class EMGBridge(InputInterface):
|
||||
|
||||
|
||||
FAQs and Troubleshootings
|
||||
-------------------------
|
||||
|
||||
- I have an ``ImportError`` with one of the interface, why? Some libraries have to be installed and configured manually. To ease the installation process, there is a docker file as well as bash scripts in the `pyrobolearn/scripts/ <https://github.com/robotlearn/pyrobolearn/tree/master/scripts>`_ folder.
|
||||
|
||||
|
||||
Future works
|
||||
------------
|
||||
|
||||
* add an interface to get the values sensed by an android/Iphone smartphone (which might have an accelerometer, gyroscope, microphone, etc.)
|
||||
* add HTC Vive interface
|
||||
* add a Facial Expression Recognition (FER) module
|
||||
* add Google assistant / Alexa
|
||||
* implement interfaces for haptic devices
|
||||
* improve the VR interface; right now, I have something for Oculus but it requires to use a Windows system in parallel (see VIDEO)
|
||||
* implement the Xsens suit interface; I also have a code for this but pretty old and it also requires a Windows system.
|
||||
@@ -0,0 +1,89 @@
|
||||
Models
|
||||
======
|
||||
|
||||
Learning models versus algorithms.
|
||||
|
||||
As shown on the following figures:
|
||||
|
||||
|
||||
Learning models can be divided into 2 categories:
|
||||
|
||||
- General function approximators (aka step-based learning models)
|
||||
- Linear models
|
||||
- Polynomial models
|
||||
- Deep Neural Networks (DNNs)
|
||||
- Gaussian processes (GPs)
|
||||
- Trajectory based learning models:
|
||||
- Dynamic Movement Primitives (DMPs)
|
||||
- Central Pattern Generators (CPGs)
|
||||
- Gaussian Mixture Models and Gaussian Mixture Regression (GMMs/GMRs)
|
||||
- Probabilistic Movement Primitives (ProMPs)
|
||||
- Kernel Movement Primitives (KMPs)
|
||||
|
||||
For few of these models, we provide a wrapper around popular libraries such as ``pytorch`` or ``gpytorch``. The other models have been reimplemented to be the most general possible.
|
||||
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
Models are independent of the other elements in PRL, but are used by other elements in PRL.
|
||||
|
||||
UML
|
||||
|
||||
The models is notably used by approximators and policies, and their (hyper-)parameters are optimized by algorithms.
|
||||
|
||||
|
||||
How to use a learning model?
|
||||
----------------------------
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import torch
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
x = torch.rand(4)
|
||||
model = prl.models.LinearModel(num_inputs=4, num_outputs=2)
|
||||
|
||||
print(model.predict(y))
|
||||
|
||||
|
||||
How to create your own model?
|
||||
-----------------------------
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
class MyModel(prl.models.Model):
|
||||
"""Description"""
|
||||
|
||||
def __init__(self, ...):
|
||||
pass
|
||||
|
||||
# implement the various abstract methods
|
||||
def ...
|
||||
|
||||
|
||||
Comparisons between the various models?
|
||||
---------------------------------------
|
||||
|
||||
A question that you might have, especially if you are new to the field, what are the differences between the different models that have been proposed in the literature? In this section, I will try to provide the differences (strengths and weaknesses) of each model, and when you should favor one over another one.
|
||||
|
||||
The below table summarizes:
|
||||
|
||||
- General function approximator (aka step-based learning models) vs trajectory based learning models: trajectory based models accepts as inputs the time and outputs a trajectory (a sequence).
|
||||
- Parametric vs Non-parametric: In a nutshell, parametric models have parameters that are tuned by the learning algorithm based on the given dataset. Depending on the number of parameters, they might require a lot of data or to have been pretrained on similar datasets. Once trained, parametric models do not need the dataset anymore. On the other hand, non-parametric models don't have parameters but few hyper-parameters. They remember each data point in the dataset, and when given a new input they compare that new input with previous ones, and outputs an estimate based on it. Non-parametric models are very good when you don't have a lot of data points and don't have a pretrained model.
|
||||
- Linear vs Non-linear: Linear models are the most simple models that makes the least assumption about the data, but can be quite limited in their expressiveness.
|
||||
- Deterministic vs Probabilistic: Deterministic models predicts a point estimate as output without any quantity that captures the uncertainty associated with that output. Meanwhile, probabilistic models provide a probability distribution for each output.
|
||||
- Discriminative vs Generative: discriminative models model learn the mapping ``p(y|x)`` where x is the input and y is the output, while generative models use to learn the data distribution ``p(x,y)``. Generative models are more powerful as given the prior ``p(x)`` or ``p(y)``, you can get back ``p(y|x)`` or ``p(x|y)``. Generative models might require more data.
|
||||
|
||||
|
||||
Future works
|
||||
------------
|
||||
|
||||
* add methods to combine different models together
|
||||
* provide few other functionalities for the various models
|
||||
@@ -0,0 +1,3 @@
|
||||
Priority Tasks
|
||||
==============
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
PyRoboLearn
|
||||
===========
|
||||
|
||||
PyRoboLearn is a Python framework in robot learning for education and research. PyRoboLearn is meant to be a free and open-source tool.
|
||||
|
||||
Goal
|
||||
|
||||
|
||||
Problem formulation
|
||||
-------------------
|
||||
|
||||
General idea.
|
||||
|
||||
- lack of benchmarks
|
||||
- lack of flexibility and modularity
|
||||
- lack of generalization
|
||||
- high coupling
|
||||
|
||||
For instance:
|
||||
|
||||
Full example.
|
||||
|
||||
|
||||
Main idea of PyRoboLearn and solution to above problem.
|
||||
|
||||
|
||||
Hardware/Software requirements
|
||||
------------------------------
|
||||
|
||||
The PyRoboLearn framework has been tested on Ubuntu 16.04 and 18.04, with Python 2.7, 3.5 and 3.6.
|
||||
|
||||
|
||||
Design Decisions
|
||||
----------------
|
||||
|
||||
While designing PRL, we focused on the five following features:
|
||||
|
||||
- modularity: design a module (i.e. class) for each different concept
|
||||
- abstraction: add a layer of abstraction for combination of low-level modules
|
||||
- reusability: easy to reuse the different modules and to combine them
|
||||
- low coupling between the different modules
|
||||
- flexibility: this is mainly achieved by favoring composition over inheritance.
|
||||
|
||||
|
||||
The Python language has been selected.
|
||||
|
||||
|
||||
.. figure:: ../UML/pyrobolearn_uml.png
|
||||
:alt: UML diagram of PyRoboLearn
|
||||
:align: center
|
||||
|
||||
UML diagram of PyRoboLearn
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
.. include:: ../../README.rst
|
||||
|
||||
Citation
|
||||
========
|
||||
|
||||
.. code-block:: latex
|
||||
|
||||
@misc{delhaisse2019pyrobolearn,
|
||||
author = {Delhaisse, Brian and Xin, Songyan and Rozo, Leonel, and Caldwell, Darwin},
|
||||
title = {PyRoboLearn: A Python Framework for Robot Learning Practitioners},
|
||||
howpublished = {\url{https://github.com/robotlearn/pyrobolearn}},
|
||||
year=2019,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
Rewards
|
||||
=======
|
||||
|
||||
In PRL, every concept is modelized as a class. This is also true for rewards which are returned by the environment as shown in the figure below (inspired by [1]_):
|
||||
|
||||
.. figure:: ../figures/environment.png
|
||||
:alt: environment
|
||||
:align: center
|
||||
|
||||
The agent-environment interaction
|
||||
|
||||
|
||||
The reward function might be defined as [1]_:
|
||||
|
||||
- :math:`r: \mathcal{S} \rightarrow \mathbb{R}`: given the state :math:`s \in \mathcal{S}`, it returns the reward value :math:`r(s)`.
|
||||
- :math:`r: \mathcal{S} \times \mathcal{A} \rightarrow \mathbb{R}`: given the state :math:`s \in \mathcal{S}` and action :math:`a \in \mathcal{A}`, it returns the reward value :math:`r(s,a)`.
|
||||
- :math:`r: \mathcal{S} \times \mathcal{A} \times \mathcal{S} \rightarrow \mathbb{R}`: given the state :math:`s \in \mathcal{S}`, action :math:`a \in \mathcal{A}`, and next state :math:`s' \in \mathcal{S}`, it returns the reward value :math:`r(s,a,s')`.
|
||||
|
||||
Note that the cost function is just minus the reward function, i.e. it is given by :math:`c(s,a,s') = -r(s,a,s')`.
|
||||
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
In PRL, all reward functions inherit from the abstract ``Reward`` class defined in `pyrobolearn/rewards/reward.py <https://github.com/robotlearn/pyrobolearn/tree/master/pyrobolearn/rewards>`_, and several methods and operations are provided.
|
||||
|
||||
You can for instance:
|
||||
|
||||
* provide the ``State`` and/or ``Action`` instances to some reward functions that will compute the reward value based on their value.
|
||||
* access to the range of the reward function.
|
||||
* add, multiply, divide, subtract, and apply basic functions such as :math:`\exp`, :math:`\cos`, :math:`\sin`, and others on reward functions. The resulting range is automatically scaled based on the operations.
|
||||
* define your own rewards/costs and reuse them in your code.
|
||||
|
||||
|
||||
How to use a particular reward?
|
||||
-------------------------------
|
||||
|
||||
Here is a short snippet showing the basic usage of reward functions:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
from pyrobolearn.rewards import FixedReward, YourReward
|
||||
|
||||
# define the simulator and world (and load what you want in it)
|
||||
sim = ...
|
||||
world = ...
|
||||
...
|
||||
|
||||
# define your state / action for your reward function
|
||||
state = ...
|
||||
action = ...
|
||||
|
||||
# define the reward function
|
||||
reward = 2 * FixedReward(3) + 0.5 * YourReward(state, action)
|
||||
|
||||
# print the range of the reward function
|
||||
print(reward.range)
|
||||
|
||||
# compute the reward value
|
||||
value = reward()
|
||||
print(value)
|
||||
|
||||
# update the state for instance
|
||||
state() # this will modify the internal state data
|
||||
|
||||
# recompute the reward value
|
||||
value = reward()
|
||||
print(value) # you will normally get a different value
|
||||
|
||||
# you can give the reward function to your RL environment
|
||||
# which will use it when calling `env.step()`.
|
||||
env = prl.envs.Env(world, state, reward)
|
||||
|
||||
|
||||
More examples on how to use the rewards can be found in `pyrobolearn/examples/rewards <https://github.com/robotlearn/pyrobolearn/tree/master/examples/rewards/>`_.
|
||||
|
||||
|
||||
How to create your own reward?
|
||||
------------------------------
|
||||
|
||||
In order to create your own reward, you have to inherit from ``Reward`` defined in `pyrobolearn/rewards/reward.py <https://github.com/robotlearn/pyrobolearn/tree/master/pyrobolearn/rewards>`_.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
class MyReward(prl.rewards.Reward):
|
||||
"""Description"""
|
||||
|
||||
def __init__(self, args):
|
||||
# initialize your reward function based on the args
|
||||
...
|
||||
|
||||
# gives initial value to your reward
|
||||
# this attribute will be used to cache the computed value
|
||||
self.value = 0
|
||||
|
||||
def _compute(self):
|
||||
# compute the reward function
|
||||
...
|
||||
# save the computed value and return it
|
||||
self.value = ...
|
||||
return self.value
|
||||
|
||||
|
||||
Once done, you will be able to use your reward function and perform operations on it (such as addition, substraction, etc).
|
||||
|
||||
|
||||
FAQs
|
||||
----
|
||||
|
||||
* If you have any questions, please submit an issue on the `Github page <https://github.com/robotlearn/pyrobolearn>`_.
|
||||
|
||||
|
||||
References:
|
||||
-----------
|
||||
|
||||
.. [1] "Reinforcement Learning: An Introduction", Sutton and Barto, 1998
|
||||
@@ -0,0 +1,337 @@
|
||||
Robots
|
||||
======
|
||||
|
||||
Robots constitute one of the main elements in the *PyRoboLearn* (PRL) framework. PRL provides a high-level abstraction and common interface to many robots, offering better consistency and generalization between them. This allows for instance to check if one particular controller or algorithm works with other robots as well.
|
||||
|
||||
More than 60+ robots are currently available in PRL covering a large range of robotic platforms. Among them, manipulators, biped robots, quadrupeds, hexapods, wheeled robots, quadcopters, and many others as shown below:
|
||||
|
||||
|
||||
GIF
|
||||
|
||||
|
||||
.. image:: ../figures/coman.png
|
||||
:width: 9%
|
||||
:alt: coman
|
||||
.. image:: ../figures/wam.png
|
||||
:width: 9%
|
||||
:alt: wam
|
||||
.. image:: ../figures/fetch.png
|
||||
:width: 9%
|
||||
:alt: fetch
|
||||
.. image:: ../figures/cassie.png
|
||||
:width: 9%
|
||||
:alt: cassie
|
||||
.. image:: ../figures/hyq2max.png
|
||||
:width: 9%
|
||||
:alt: hyq2max
|
||||
.. image:: ../figures/phantomx.png
|
||||
:width: 9%
|
||||
:alt: phantomx
|
||||
.. image:: ../figures/pleurobot.png
|
||||
:width: 9%
|
||||
:alt: pleurobot
|
||||
.. image:: ../figures/softhand.png
|
||||
:width: 9%
|
||||
:alt: softhand
|
||||
.. image:: ../figures/centauro.png
|
||||
:width: 9%
|
||||
:alt: baxter
|
||||
.. image:: ../figures/walkman.png
|
||||
:width: 9%
|
||||
:alt: walkman
|
||||
|
||||
Note that for few of them such as the ones that require the simulation of fluids (e.g. quadcopters). If the simulator does not simulate fluids, the corresponding robot class implements a simple dynamics simulation. For such classes, as I did not spend too much time one it, some improvements might be needed for better realism.
|
||||
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The most abstract class is the ``Body`` class which is described in `pyrobolearn/robots/base.py <https://github.com/robotlearn/pyrobolearn/blob/master/pyrobolearn/robots/base.py>`_. From it, you can already access to multiple functionalities/attributes, such as its position and orientation. It only depends on the simulator.
|
||||
|
||||
|
||||
.. figure:: ../UML/robots.png
|
||||
:alt: UML diagram for Robot
|
||||
:align: center
|
||||
|
||||
UML diagram for Robot
|
||||
|
||||
|
||||
Inheriting from one of its child classes is the most interesting (for our purpose) ``Robot`` class, described in `robot.py <https://github.com/robotlearn/pyrobolearn/blob/master/pyrobolearn/robots/robot.py>`_. It is the parent class of several classes such as:
|
||||
|
||||
- ``Manipulator`` defined in `manipulator.py <https://github.com/robotlearn/pyrobolearn/blob/master/pyrobolearn/robots/manipulator.py>`_
|
||||
- ``LeggedRobot`` defined in `legged_robot.py <https://github.com/robotlearn/pyrobolearn/blob/master/pyrobolearn/robots/legged_robot.py>`_
|
||||
- ``WheeledRobot`` defined in `wheeled_robot.py <https://github.com/robotlearn/pyrobolearn/blob/master/pyrobolearn/robots/wheeled_robot.py>`_
|
||||
- ``Hand`` defined in `hand.py <https://github.com/robotlearn/pyrobolearn/blob/master/pyrobolearn/robots/hand.py>`_
|
||||
- etc.
|
||||
|
||||
Note that ``Robot`` only depends on the simulator interface (aggregation relationship), and is independent of other modules in PRL (at the exception of some util methods that are useful to perform some transformations).
|
||||
|
||||
|
||||
How to use a robot in PRL?
|
||||
--------------------------
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
from itertools import count
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create simulator
|
||||
simulator = prl.simulators.Bullet()
|
||||
|
||||
# create basic world (with floor and gravity)
|
||||
world = prl.worlds.BasicWorld(simulator)
|
||||
|
||||
# load robot in the world at the specified (x, y) position (you can also give a (x,y,z) position)
|
||||
# For other possible parameters, check the method documentation.
|
||||
robot = world.load_robot('robot_name', position=[0., 0.], ...)
|
||||
|
||||
# print some info about the robot
|
||||
robot.print_info()
|
||||
print(dir(robot)) # print available methods
|
||||
|
||||
# main loop
|
||||
for _ in count():
|
||||
|
||||
# perform something with the robot for instance some kinematic / dynamic control
|
||||
...
|
||||
|
||||
# perform a step in the world and sleep for `sim.dt`
|
||||
world.step(sim.dt)
|
||||
|
||||
|
||||
You can check for more examples in the `examples/robots <https://github.com/robotlearn/pyrobolearn/tree/master/examples/robots>`_ folder. You can also check for `examples/kinematics <https://github.com/robotlearn/pyrobolearn/tree/master/examples/kinematics>`_ and `examples/dynamics <https://github.com/robotlearn/pyrobolearn/tree/master/examples/dynamics>`_.
|
||||
|
||||
- Kinematics
|
||||
- Dynamics
|
||||
|
||||
|
||||
How to create your own robot?
|
||||
-----------------------------
|
||||
|
||||
To illustrate how to create your own robot, let's assume you want to create a humanoid robot (biped and bi-manipulator) called ``Asimov``.
|
||||
|
||||
1. First, you have to get (or create) its URDF file and the associated meshes. Let's put them in a directory called ``asimov``, and move it in the ``pyrobolearn/robots/urdfs/`` folder where all the other URDFs are.
|
||||
|
||||
2. If you want to use it directly and to not create a specific class, you can just call:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
# create simulator and basic world
|
||||
simulator = prl.simulators.Bullet()
|
||||
|
||||
# create world
|
||||
world = prl.worlds.BasicWorld(simulator)
|
||||
|
||||
# create robot
|
||||
urdf = "path/to/urdf"
|
||||
position = None # position [x,y,[z]]. If None, by default, it will be set to (0,0,0)
|
||||
orientation = None # quaternion [x,y,z,w]. If None, by default, it will be set to (0,0,0,1)
|
||||
robot = Robot(simulator, urdf, position, orientation, fixed_base=False)
|
||||
|
||||
# main loop
|
||||
while True:
|
||||
# do something with robot
|
||||
...
|
||||
|
||||
# perform a step in the world and pause for `sim.dt`
|
||||
world.step(sim.dt)
|
||||
|
||||
3. Instead of the second point, let's create a proper class ``Asimov`` that inherits from the ``BipedRobot`` and ``BiManipulator`` (and thus inherits their functionalities) in a Python file ``asimov.py``:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
#!/usr/bin/env python
|
||||
"""Short description about your robot
|
||||
|
||||
Long description about the robot
|
||||
"""
|
||||
|
||||
# import libraries you need
|
||||
import ...
|
||||
|
||||
# import the classes to inherit from
|
||||
from pyrobolearn.robots.legged_robot import BipedRobot
|
||||
from pyrobolearn.robots.manipulator import BiManipulator
|
||||
|
||||
|
||||
class Asimov(BipedRobot, BiManipulator):
|
||||
r"""Asimov Robot
|
||||
|
||||
Add description about the robot here, such as the number of degrees of freedom, the various sensors/actuators that are available.
|
||||
|
||||
References:
|
||||
- [1] reference 1; e.g. link to the robot webpage
|
||||
- [2] reference 2: e.g. link to original URDF
|
||||
"""
|
||||
|
||||
# define static variables here, e.g.
|
||||
BASE_HEIGHT = 1
|
||||
|
||||
def __init__(self, simulator, position=(0, 0, 0), orinetation=(0, 0, 0, 1), fixed_base=False, scale=1.,
|
||||
urdf=os.path.dirname(os.path.abspath(__file__)) + '/relative/path/to/your/urdf/wrt/this/python/file.urdf')
|
||||
|
||||
# check parameters and set default parameters if necessary
|
||||
if position is None: # it receives None notably when the world load the robot if a position is not specified
|
||||
position = (0, 0, 0)
|
||||
if len(position) == 2: # assume (x,y) are given
|
||||
position = tuple(position) + (self.BASE_HEIGHT,)
|
||||
if orientation is None: # it receives None notably when the world load the robot if an orientation is not specified
|
||||
orientation = (0, 0, 0, 1) # quaternion [x,y,z,w]
|
||||
if fixed_base is None: # it receives None notably when the world load the robot if fixed_base is not specified
|
||||
fixed_base = False
|
||||
|
||||
# call parent constructor
|
||||
super(Asimov, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
# define common attributes to all bimanipulator/biped robot (see their respective classes)
|
||||
|
||||
# for bimanipulator
|
||||
self.arms = [] # list of arms where each arm is a list of link ids
|
||||
self.hands = [] # list of end-effector/hand link ids
|
||||
|
||||
# default values set in BiManipulator class that you can modify if necessary
|
||||
# self.left_arm_id, self.left_hand_id = 0, 0 # used e.g. for self.arms[self.left_arm_id]
|
||||
# self.right_arm_id, self.right_hand_id = 1, 1 # used e.g. for self.arms[self.right_arm_id]
|
||||
|
||||
# for biped (similar than for bimanipulator): check corresponding `BipedRobot` class
|
||||
self.legs = [] # list of legs where a leg is a list of links
|
||||
self.feet = [] # list of feet ids
|
||||
...
|
||||
|
||||
# define your own sensors and actuators
|
||||
...
|
||||
|
||||
|
||||
3. If you want to be able to load your robot from the world using its name (by calling ``world.load_robot('asimov')``), add the Python file ``asimov.py`` in the `pyrobolearn/robots/ <https://github.com/robotlearn/pyrobolearn/tree/master/pyrobolearn/robots>`_ folder. The ``__init__.py`` inside that folder will automatically go through all the files and add the robots inside the ``implemented_robots`` list which is accessed by ``World``. Note that you can also access this list by calling ``pyrobolearn.robots.implemented_robots``. If you also want to be able to call your robot using ``from pyrobolearn.robots import Asimov``, you will have to add the line ``from .asimov import Asimov`` in the `pyrobolearn/robots/__init__.py <https://github.com/robotlearn/pyrobolearn/blob/master/pyrobolearn/robots/__init__.py>`_.
|
||||
|
||||
4. Now, you can call your robot in the framework.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
from itertools import count
|
||||
import pyrobolearn as prl
|
||||
|
||||
simulator = prl.simulators.Bullet()
|
||||
|
||||
# create world and load robot inside (recommended)
|
||||
world = prl.worlds.BasicWorld(simulator)
|
||||
robot = world.load_robot('asimov')
|
||||
# or directly created the robot in the simulator (not recommended unless you are doing experiments on the real robot
|
||||
# and thus the world is not useful)
|
||||
# robot = prl.robots.Asimov(simulator)
|
||||
robot.print_info()
|
||||
|
||||
# main loop
|
||||
for _ in count():
|
||||
world.step(sleep_dt=sim.dt)
|
||||
|
||||
|
||||
Sensors and Actuators
|
||||
---------------------
|
||||
|
||||
* Sensors
|
||||
* Actuators
|
||||
|
||||
|
||||
FAQs and Troubleshootings
|
||||
-------------------------
|
||||
|
||||
- The mass/inertia matrix of some links are not correct in the simulator, what should I do?
|
||||
- If you use the Bullet simulator (which uses ``pybullet``), you have to specify the mass and inertia matrix for each link. If a link doesn't have these attributes defined, pybullet automatically attribute a mass of 1kg and an identity inertia matrix (which is ridiculous huge). Normally, links without a mass and inertia matrices defined in a URDF file are dummy links that are used to represent a reference frame. To set a reasonable inertia matrix, please refer to `"Adding Physical and Collision Properties to a URDF Model" <http://wiki.ros.org/urdf/Tutorials/Adding%20Physical%20and%20Collision%20Properties%20to%20a%20URDF%20Model>`_ and `"Inertial parameters of triangle meshes" <http://gazebosim.org/tutorials?tut=inertia&cat=build_robot>`_.
|
||||
- It is possible that some masses / inertia matrices have not been correctly set in the original URDF. I cleaned most of the URDF files but some links might have escaped my attention. Please open an issue on `Github <https://github.com/robotlearn/pyrobolearn>`_, or check the 2 `links <http://wiki.ros.org/urdf/Tutorials/Adding%20Physical%20and%20Collision%20Properties%20to%20a%20URDF%20Model>`_ `above <http://gazebosim.org/tutorials?tut=inertia&cat=build_robot>`_ on how to set reasonable inertia values.
|
||||
|
||||
- How to convert a xacro file to a URDF file? Type ``rosrun xacro xacro --inorder path/to/<robot>.urdf.xacro > <robot>.urdf`` or ``rosrun xacro xacro.py --inorder path/to/<robot>.urdf.xacro > <robot>.urdf``
|
||||
|
||||
- When I set the ``fixed_base`` to ``False``, the robot has still a fixed base, what is happening? The first link (often called base_link or world_link in most URDF files) shouldn't have a mass/inertia of zero, this causes the robot to have a fixed base. Remove the corresponding tag from the urdf.
|
||||
|
||||
- What are the differences when a robot has a floating-based and a fixed base? When the robot has a floating base, the total number of degrees of freedom becomes 6 + the number of actuated joints. This appears when computing the Jacobian and Inertia matrices.
|
||||
|
||||
- I noticed that some functionalities are missing in one of the robot class? I probably forgot to implement it. Please open an issue on `Github <https://github.com/robotlearn/pyrobolearn>`_ or create a pull request.
|
||||
|
||||
- There is an error in one of the functionalities? Or, I have another question or want to suggest an improvement? Please open an issue on `Github <https://github.com/robotlearn/pyrobolearn>`_ or a create a pull request.
|
||||
|
||||
|
||||
Future works
|
||||
------------
|
||||
|
||||
- add more robots. Here are few other robots that might interest the users:
|
||||
- `hexapods <https://github.com/resibots/hexapod_ros/tree/master/hexapod_description>`_
|
||||
- `ROS robots <https://robots.ros.org/>`_
|
||||
- `Universal robots <https://github.com/ros-industrial/universal_robot>`_
|
||||
- improve the flexibility/modularity by allowing to remove/add/replace links to/from the main robot. For instance:
|
||||
- add a gripper to a manipulator robot, or replace a gripper with another
|
||||
- remove a leg from a legged robot (which is interesting to simulate damage recovery scenarios)
|
||||
- might need to define different URDFs for different simulators
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
All the robots were found in the following github repositories (and several were cleaned by me):
|
||||
|
||||
- `Aibo <https://github.com/dkotfis/aibo_ros>`_
|
||||
- `Allegrohand <https://github.com/simlabrobotics/allegro_hand_ros>`_
|
||||
- `Ant <https://github.com/bulletphysics/bullet3/tree/master/examples/pybullet/gym/pybullet_data/mjcf>`_
|
||||
- Atlas: `1 <https://github.com/openai/roboschool>`_, `2 <https://github.com/erwincoumans/pybullet_robots>`_
|
||||
- `Ballbot <https://github.com/CesMak/bb>`_
|
||||
- `Baxter <https://github.com/RethinkRobotics/baxter_common>`_
|
||||
- BB8: `1 <http://www.theconstructsim.com/bb-8-gazebo-model/>`_, `2 <https://github.com/eborghi10/BB-8-ROS>`_
|
||||
- `Blackbird <https://hackaday.io/project/160882-blackbird-bipedal-robot>`_
|
||||
- `Cartpole <https://github.com/bulletphysics/bullet3/blob/master/data/cartpole.urdf>`_ but modified to be able to have multiple links specified at runtime
|
||||
- Cassie: `1 <https://github.com/UMich-BipedLab/Cassie_Model>`_, `2 <https://github.com/agilityrobotics/cassie-gazebo-sim>`_, `3 <https://github.com/erwincoumans/pybullet_robots>`_
|
||||
- `Centauro <https://github.com/ADVRHumanoids/centauro-simulator>`_
|
||||
- `Cogimon <https://github.com/ADVRHumanoids/iit-cogimon-ros-pkg>`_
|
||||
- `Coman <https://github.com/ADVRHumanoids/iit-coman-ros-pkg>`_
|
||||
- `Crab <https://github.com/tuuzdu/crab_project>`_
|
||||
- `Cubli <https://github.com/xinsongyan/cubli>`_
|
||||
- `Darwin <https://github.com/HumaRobotics/darwin_description>`_
|
||||
- `e.Do <https://github.com/Comau/eDO_description>`_
|
||||
- `E-puck <https://github.com/gctronic/epuck_driver_cpp>`_
|
||||
- `F10 racecar <https://github.com/erwincoumans/pybullet_robots/tree/master/data/f10_racecar>`_
|
||||
- `Fetch <https://github.com/fetchrobotics/fetch_ros>`_
|
||||
- `Franka Emika <https://github.com/frankaemika/franka_ros>`_
|
||||
- `Half Cheetah <https://github.com/bulletphysics/bullet3/tree/master/examples/pybullet/gym/pybullet_data/mjcf>`_
|
||||
- `Hopper <https://github.com/bulletphysics/bullet3/tree/master/examples/pybullet/gym/pybullet_data/mjcf>`_
|
||||
- `Hubo <https://github.com/robEllenberg/hubo-urdf>`_
|
||||
- `Humanoid <https://github.com/bulletphysics/bullet3/tree/master/examples/pybullet/gym/pybullet_data/mjcf>`_
|
||||
- `Husky <https://github.com/husky/husky>`_
|
||||
- `HyQ <https://github.com/iit-DLSLab/hyq-description>`_
|
||||
- `HyQ2Max <https://github.com/iit-DLSLab/hyq2max-description>`_
|
||||
- ICub: `1 <https://github.com/robotology-playground/icub-models>`_, `2 <https://github.com/robotology-playground/icub-model-generator>`_. There are currently few problems with this robot.
|
||||
- `Jaco <https://github.com/JenniferBuehler/jaco-arm-pkgs>`_
|
||||
- KR5: `1 <https://github.com/a-price/KR5sixxR650WP_description>`_, `2 <https://github.com/ros-industrial/kuka_experimental>`_
|
||||
- Kuka IIWA: `1 <https://github.com/IFL-CAMP/iiwa_stack>`_, `2 <https://github.com/bulletphysics/bullet3/tree/master/data/kuka_iiwa>`_
|
||||
- Kuka LWR: `1 <https://github.com/CentroEPiaggio/kuka-lwr>`_, `2 <https://github.com/bulletphysics/bullet3/tree/master/data/kuka_lwr>`_
|
||||
- `Laikago <https://github.com/erwincoumans/pybullet_robots>`_
|
||||
- `Little Dog <https://github.com/RobotLocomotion/LittleDog>`_
|
||||
- `Manipulator2D <https://github.com/domingoesteban/robolearn_robots_ros>`_
|
||||
- `Minitaur <https://github.com/bulletphysics/bullet3/tree/master/examples/pybullet/gym/pybullet_data/quadruped>`_
|
||||
- `Lincoln MKZ car <https://bitbucket.org/DataspeedInc/dbw_mkz_ros>`_
|
||||
- `Morphex <https://gist.github.com/lanius/cb8b5e0ede9ff3b2b2c1bc68b95066fb>`_
|
||||
- Nao: `1 <https://github.com/ros-naoqi/nao_robot>`_, and `2 <https://github.com/ros-naoqi/nao_meshes>`_
|
||||
- OpenDog: `1 <https://github.com/XRobots/openDog>`_, and `2 <https://github.com/wiccopruebas/opendog_project>`_
|
||||
- `Pepper <https://github.com/ros-naoqi/pepper_robot>`_
|
||||
- `Phantom X <https://github.com/HumaRobotics/phantomx_description>`_
|
||||
- `Pleurobot <https://github.com/KM-RoBoTa/pleurobot_ros_pkg>`_
|
||||
- `PR2 <https://github.com/pr2/pr2_common>`_
|
||||
- `Quadcopter <https://github.com/wilselby/ROS_quadrotor_simulator>`_
|
||||
- `Rhex <https://github.com/grafoteka/rhex>`_
|
||||
- `RRbot <https://github.com/ros-simulation/gazebo_ros_demos>`_
|
||||
- Sawyer: `1 <https://github.com/RethinkRobotics/sawyer_robot>`_, `2 <https://github.com/erwincoumans/pybullet_robots>`_
|
||||
- `SEA hexapod <https://github.com/alexansari101/snake_ws>`_
|
||||
- `SEA snake <https://github.com/alexansari101/snake_ws>`_
|
||||
- `Shadow hand <https://github.com/shadow-robot/sr_common>`_
|
||||
- `Soft hand <https://github.com/CentroEPiaggio/pisa-iit-soft-hand>`_
|
||||
- `Swimmer <https://github.com/bulletphysics/bullet3/tree/master/examples/pybullet/gym/pybullet_data/mjcf>`_
|
||||
- `Valkyrie <https://github.com/openhumanoids/val_description>`_
|
||||
- `Walker 2D <https://github.com/bulletphysics/bullet3/tree/master/examples/pybullet/gym/pybullet_data/mjcf>`_
|
||||
- `Walk-man <https://github.com/ADVRHumanoids/iit-walkman-ros-pkg>`_
|
||||
- `Wam <https://github.com/jhu-lcsr/barrett_model>`_
|
||||
- `Youbot <https://github.com/youbot>`_: this includes the youbot base without any arms, one kuka arm, 2 kuka arms, and the kuka arm without the wheeled base.
|
||||
@@ -0,0 +1,97 @@
|
||||
Simulators
|
||||
==========
|
||||
|
||||
The simulator is the starting point in the **PyRoboLearn** (PRL) framework. To avoid a tight coupling with a particular simulator, a ``Simulator`` interface class (from which all the other simulators inherit from) has been implemented. Other .
|
||||
|
||||
We provide the ``Bullet`` interface, which uses the ``pybullet`` library.
|
||||
|
||||
The general idea is that you would be able to change the simulator if you wish without having to modify any other lines of code. See example below.
|
||||
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The important goal when designing the simulators was that it should be a stand alone interface.
|
||||
|
||||
|
||||
.. figure:: ../UML/simulator.png
|
||||
:alt: UML diagram for Simulators
|
||||
:align: center
|
||||
|
||||
UML diagram for simulators
|
||||
|
||||
|
||||
Currently, the only fully functional simulator is ``Bullet``. While other simulators have been considered such as Gazebo (with ROS), Mujoco, Dart, and others, few of them required a particular license or do not have strong Python bindings.
|
||||
|
||||
Note that each simulator implements static methods which provide information about the simulator itself; if it can for instance simulate fluids or not, etc.
|
||||
|
||||
|
||||
How to use a particular simulator in PRL?
|
||||
-----------------------------------------
|
||||
|
||||
For the moment, the only fully operational interface is ``Bullet``. Some few other interfaces have been partially implemented (see Future works). Here is a snippet on how to use the ``Bullet`` simulator in PRL:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from itertools import count
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create simulator
|
||||
simulator = prl.simulators.Bullet()
|
||||
# later: you would be able to change the simulator by `BulletROS` or `RBDL_ROS` to command a real robot using ROS
|
||||
|
||||
# create world, robots, etc
|
||||
...
|
||||
|
||||
# main loop
|
||||
for _ in count():
|
||||
|
||||
# do something
|
||||
...
|
||||
|
||||
# perform a step in the world and sleep for `sim.dt`
|
||||
sim.step(sim.dt)
|
||||
|
||||
|
||||
You can check for more examples in the `examples/simulators <https://github.com/robotlearn/pyrobolearn/tree/master/examples/simulators>`_ folder.
|
||||
|
||||
|
||||
How to create an interface to a simulator?
|
||||
------------------------------------------
|
||||
|
||||
To create your own Simulator, you have to inherit from the ``Simulator`` class defined in `pyrobolearn/simulators/simulator.py <https://github.com/robotlearn/pyrobolearn/blob/master/pyrobolearn/simulators/simulator.py>`_.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
class MySimulator(prl.simulators.Simulator):
|
||||
"""Description"""
|
||||
# implement all the abstract methods in Simulator
|
||||
|
||||
|
||||
FAQs and Troubleshootings
|
||||
-------------------------
|
||||
|
||||
* What are the differences between `BulletClient <https://github.com/bulletphysics/bullet3/blob/master/examples/pybullet/gym/pybullet_utils/bullet_client.py>`_ and the ``Bullet`` defined in PRL? There are few differences but the design of the abstract ``Simulator`` class as well as the `Bullet` class was heavily inspired by the methods provided in PyBullet. The subtil differences include:
|
||||
* a full documentation embedded in the code of ``Bullet``. The documentation for each function provided in the original pybullet is described on a Google doc available `here <https://docs.google.com/document/d/10sXEhzFRSnvFcl3XxNGhnD4N2SedqwdAvK3dsihxVUA>`_. This is not optimal when coding where a user often wants to access the documentation through the code using ``function?`` or ``help(function)`` in a Python console.
|
||||
* follow the PEP8 style guideline. For instance, the names of the method are given by ``create_collision_shape`` instead of ``createCollisionShape``.
|
||||
* automatic conversion to numpy arrays from lists that are returned by ``pybullet``, and vice-versa. Some methods (not all of them) in the original pybullet raises an error when given a numpy array. I identified these methods and convert these numpy arrays to lists. Also, some matrices returned by some methods in the original pybullet are returned as a list of int/float instead of numpy arrays. The conversion to numpy array and the reshaping to the correct shapes is thus also performed in the ``Bullet`` class.
|
||||
* enforce consistency; for instance, some angles that were returned from or provided to some methods in the original pybullet, were for some in degrees while for others in radians. This can lead to some bugs that could be hard to detect if the user is not aware of that. In ``Bullet``, all the returned/provided angles are in radians.
|
||||
|
||||
|
||||
Future works
|
||||
------------
|
||||
|
||||
My main objectives for future works are the implementation of:
|
||||
|
||||
- the Mujoco interface; I originally did not start with it as it is closed-source and requires a License. However, it is used a lot in research and thus it could be interesting to have it as well.
|
||||
- the Gazebo-ROS interface; a part has already been implemented but it is far from over.
|
||||
- the Isaac interface if Nvidia provided a nice Python API.
|
||||
|
||||
Possible other future works might include the implementation of:
|
||||
- the DART interface; there is a minimal implementation of it when I was playing around with it
|
||||
- the opensim interface; this interface is for musculoskeletal models but this can be interesting when testing algorithms/models.
|
||||
@@ -0,0 +1,108 @@
|
||||
States
|
||||
======
|
||||
|
||||
In PRL, every concept is modelized as a class. This is also true for states which are returned by the environment.
|
||||
|
||||
.. figure:: ../figures/environment.png
|
||||
:alt: environment
|
||||
:align: center
|
||||
|
||||
The agent-environment interaction
|
||||
|
||||
|
||||
States are given to the policy and the environment. The environment is responsible to update them while policies read their ``data`` and feed it to the underlying learning model. In the case we use a physics simulator like PyBullet, the environment performs one step in the simulation and calls the ``states()`` which updates the ``data`` they contained. Instead, if you have a dynamical model function, the environment can call this one to update the ``data`` of the various ``states`` without having to call the ``states()`` itself to update their values.
|
||||
|
||||
States can also be given to dynamical models (which predicts the next state given the current state and last action), value function approximators (which predicts a scalar value given a state and possibly an action), reward functions, etc.
|
||||
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
UML
|
||||
|
||||
|
||||
How to use a particular state?
|
||||
------------------------------
|
||||
|
||||
Let's assume you have a quadruped robot, and you would like to get its joint positions, velocities, and base position.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
from itertools import count
|
||||
import pyrobolearn as prl
|
||||
from pyrobolearn.states import BasePositionState, JointPositionState, JointVelocityState
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# load robot
|
||||
robot = prl.robots.HyQ2Max(sim)
|
||||
|
||||
# create the states
|
||||
base_pos_state = BasePositionState(robot)
|
||||
joint_pos_state = JointPositionState(robot, joint_ids=robot.legs) # you can specify which joints you would like to get the position
|
||||
joint_vel_state = JointVelocityState(robot, joint_ids=robot.legs) # you can specify which joints you would like to get the velocity
|
||||
|
||||
state = base_pos_state + joint_pos_state + joint_vel_state
|
||||
|
||||
# run simulation
|
||||
for t in count():
|
||||
# call and print the state
|
||||
print(state())
|
||||
|
||||
# perform a step in the world
|
||||
world.step(sim.dt)
|
||||
|
||||
|
||||
All the states accept also as inputs:
|
||||
|
||||
- ``window_size``: size (by default, it is set to one)
|
||||
- ``ticks``: the number of simulation ticks to sleep before getting the next state.
|
||||
|
||||
In the example above, for joint states, you could also specify the joints that you would like to get the states from by setting ``joint_ids``. Note that in order to be able to generalize to other robots, avoid to give manually the joint ids but instead gives an attribute of the robot, like, ``robot.legs`` (wich is a list containing the joint ids associated with each leg).
|
||||
|
||||
Now, let's assume that you forgot to include the robot's base orientation and its linear/angular velocity in the state. In other frameworks, it is very likely that you would have to change manually the state and everything that depends on it (the policy / value function approximator which accepts as input the state, the step function in the environment which compute the next state, possibly the reward function which is often based on the current state, etc). In PRL, everything is automatized, and thus setting:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
state = state + BaseOrientationState(robot) + BaseLinearVelocity(robot)
|
||||
|
||||
will automatically results the other components to update their input size or because this new state is provided to them.
|
||||
|
||||
|
||||
How to create your own state?
|
||||
-----------------------------
|
||||
|
||||
Let's assume that you want to create a state that accepts as inputs the game controller .
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
class MyState(prl.states.State): # inherit from the abstract State class
|
||||
"""Description"""
|
||||
|
||||
def __init__(self, ...):
|
||||
|
||||
super(MyState, self).__init__(...)
|
||||
|
||||
|
||||
FAQs
|
||||
----
|
||||
|
||||
|
||||
Other functionalities
|
||||
---------------------
|
||||
|
||||
- `State generator <https://github.com/robotlearn/pyrobolearn/tree/master/pyrobolearn/states/generators>`_: generate a state (used as initial state generator)
|
||||
- `State processor <https://github.com/robotlearn/pyrobolearn/tree/master/pyrobolearn/states/processors>`_: process the given state (before giving it to another model such as a policy)
|
||||
|
||||
|
||||
Future works
|
||||
------------
|
||||
|
||||
* add a ``rate`` attribute to the states which is used when we set the real-time on the simulator. Or better, using the ``ticks`` and ``sim.dt`` infer the rate.
|
||||
@@ -0,0 +1,82 @@
|
||||
Worlds
|
||||
======
|
||||
|
||||
The world is the second important item in PRL; it is, with the ``Body`` class (see next section), the only class that can access the simulator. As it name implies, it allows you to create a world in the simulator, load various objects in it, and change the world's and objects' physical properties. From it, you can also access to the main camera (if the GUI is enabled in the simulator), and move it as you wish. The world can be seen as a wrapper around the simulator which provides you extra functionalities where each function calls different methods of the simulator. Finally, the world also allows you to load and generate terrains.
|
||||
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
As it can be seen on the UML diagram below the ``World`` depends on the ``Simulator`` and the various ``Body`` (see next section) loaded in it (as well as few util functions).
|
||||
|
||||
|
||||
.. figure:: ../UML/world.png
|
||||
:alt: UML diagram for World
|
||||
:align: center
|
||||
|
||||
UML diagram for world
|
||||
|
||||
|
||||
Later, we will see that world is notably given to the environment along with the states and rewards.
|
||||
|
||||
|
||||
How to use the world in PRL?
|
||||
----------------------------
|
||||
|
||||
Here is a snippet showing how to create a simple world in PRL:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
from itertools import count
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create simulator
|
||||
simulator = prl.simulators.Bullet()
|
||||
|
||||
# create basic world (with floor and gravity)
|
||||
world = prl.worlds.BasicWorld(simulator)
|
||||
|
||||
# load a sphere in the world
|
||||
sphere = world.load_sphere(position=[0, 0, 5])
|
||||
|
||||
# run the simulator
|
||||
for t in count():
|
||||
# follow the sphere falling with the main camera
|
||||
world.camera.follow(sphere, distance=2)
|
||||
|
||||
# perform a step in the simulator and sleep for `sim.dt`
|
||||
world.step()
|
||||
|
||||
|
||||
Note that you can get access to the world camera, and change its position and orientation. You can also follow an object moving with the camera as done in the code above.
|
||||
|
||||
For more examples, you can check the `examples/worlds <https://github.com/robotlearn/pyrobolearn/tree/master/examples/worlds>`_ folder.
|
||||
|
||||
|
||||
How to create your own world?
|
||||
-----------------------------
|
||||
|
||||
Creating your own world basically boils down to inheriting from the ``World`` or ``BasicWorld`` (if you want a floor and enable gravity by default) class, and write in the constructor what you want your world to load when instantiated.
|
||||
|
||||
|
||||
|
||||
FAQs and Troubleshootings
|
||||
-------------------------
|
||||
|
||||
- Why do the ``Body`` class (and all the classes that inherit from it such as ``Robot``) can access the simulator as well?
|
||||
- This is because, creating a world when the ``Simulator`` consists to be the real world doesn't make much sense. The ``Robot`` is completely independent of the ``World``, while the converse is not true.
|
||||
- I got an error while loading a 3D object / mesh?
|
||||
- The most common error is because the given format is not supported by the simulator. Try to convert it in ``.obj`` using for instance `meshlab <http://www.meshlab.net/>`_ (which is an open-source free tool to process and edit 3D meshes)
|
||||
|
||||
|
||||
Where can I find 3d models to load in the world?
|
||||
------------------------------------------------
|
||||
|
||||
- If it a combination of simple shapes linked together, you can build it in the simulator.
|
||||
- `Pybullet data <https://github.com/bulletphysics/bullet3/tree/master/data>`_
|
||||
- `Gazebo database <https://bitbucket.org/osrf/gazebo_models/src/default/>`_
|
||||
- `Turbosquid <www.turbosquid.com>`_
|
||||
- `free3d <free3d.com>`_
|
||||
- `sketchfab <sketchfab.com>`_
|
||||
@@ -1,9 +0,0 @@
|
||||
## Examples
|
||||
|
||||
In this folder, you will find different examples on how to use the framework.
|
||||
|
||||
You can check the following folders:
|
||||
- `gym/cartpole`: policies are trained with different algorithms on the gym Cartpole environment.
|
||||
- `robots`: check how to load a specific robot into the world.
|
||||
- `states`: how to query the states / observations.
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
Examples
|
||||
========
|
||||
|
||||
In this folder, you will find different examples on how to use the framework.
|
||||
|
||||
Warning: this folder is currently being updated; few files might still have some bugs or not
|
||||
implemented completely. Some other folders will be added in the upcoming days.
|
||||
|
||||
You can check the following folders on:
|
||||
|
||||
- ``simulators``: how to use a particular simulator. Currently, the Bullet simulator is the one fully operational.
|
||||
- ``worlds``: how to create a world in the simulator, load various objects inside and interact with them, use the camera, and load or generate terrains.
|
||||
- ``robots``: how to load a specific robot (biped, quadruped, wheeled, etc) into the world.
|
||||
- ``interfaces``: the various interfaces (game controllers, webcam, etc) and bridges that you can use.
|
||||
- ``kinematics``: how to use forward and inverse kinematics as well as position and velocity control.
|
||||
- ``dynamics``: how to use forward and inverse dynamics as well as force control.
|
||||
- ``manipulability``: how to use the velocity and dynamic manipulability ellipsoids.
|
||||
- ``states``: how to query the states / observations.
|
||||
- ``models``: the different learning models that you can use.
|
||||
- ``imitation``: how to use imitation learning with the framework.
|
||||
- ``gym/cartpole``: policies that are trained with different algorithms on the gym Cartpole environment.
|
||||
@@ -0,0 +1,9 @@
|
||||
## Robot dynamics
|
||||
|
||||
We provide examples on how to perform forward and inverse dynamics, as well as force control.
|
||||
|
||||
References:
|
||||
- [1] "Robotics: Modelling, Planning and Control", Siciliano et al., 2010
|
||||
- [2] "Springer Handbook of Robotics", Siciliano et al., 2008
|
||||
- [3] "Rigid Body Dynamics Algorithms", Featherstone, 2008
|
||||
- [4] [Lecture on Impedance Control](http://www.diag.uniroma1.it/~deluca/rob2_en/15_ImpedanceControl.pdf) by Prof. De Luca, Universita di Roma
|
||||
@@ -0,0 +1,20 @@
|
||||
### Force control
|
||||
|
||||
In a nutshell, you have different control modes:
|
||||
|
||||
* motion control: specify the desired task (or joint) positions / velocities
|
||||
* force control: specify the desired task (or joint) forces
|
||||
* indirect force control:
|
||||
* impedance control
|
||||
* admittance control
|
||||
* direct force control:
|
||||
* hybrid force/position control
|
||||
* parallel force/position control
|
||||
|
||||
Here are the few examples that you can find in this folder:
|
||||
1. `no_forces.py`: this example loads a RRBot robot and disable the motors. It does not apply any joint torques.
|
||||
2. `gravity_compensation.py`: compute the necessary joint torques to compensate for gravity.
|
||||
3. `attractor_point.py`: compute the necessary joint torques (using impedance control) such that the end-effector
|
||||
is attracted by a 3D Cartesian point.
|
||||
|
||||
For these 3 above examples, try to move the robot's end effector with your mouse and see what happens.
|
||||
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
"""Attractor point using impedance control with RRBot
|
||||
|
||||
Try to move the end-effector using the mouse, and see what happens. Compare the obtained results with
|
||||
`force/no_forces.py` and `force/gravity_compensation.py`.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from itertools import count
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# Create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create world
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load robot
|
||||
robot = prl.robots.RRBot(sim)
|
||||
robot.disable_motor() # disable motors; comment the `robot.set_joint_torques(torques)` to see what happens
|
||||
robot.print_info()
|
||||
robot.change_transparency()
|
||||
|
||||
# define variables
|
||||
link_id = robot.get_link_ids('hokuyo_link') # the link we are interested to
|
||||
com_frame = robot.get_link_states(link_id)[2]
|
||||
x_des = robot.get_link_world_positions(link_id) # desired cartesian position
|
||||
|
||||
# gains
|
||||
K = 100 * np.identity(3)
|
||||
D = 2 * np.sqrt(K) # critically damped
|
||||
D = 3 * D # manually increase damping
|
||||
|
||||
# draw a sphere at the desired location
|
||||
world.load_visual_sphere(position=x_des, radius=0.1, color=(0, 1, 0, 0.5))
|
||||
|
||||
|
||||
# run simulator
|
||||
for _ in count():
|
||||
# get current joint positions, velocities, accelerations
|
||||
q = robot.get_joint_positions()
|
||||
dq = robot.get_joint_velocities()
|
||||
ddq = np.zeros(len(q))
|
||||
|
||||
# get current link position and velocity
|
||||
x = robot.get_link_world_positions(link_id)
|
||||
dx = robot.get_link_world_linear_velocities(link_id)
|
||||
|
||||
# compute torques (Coriolis, centrifugal and gravity compensation) using inverse dynamics
|
||||
torques = robot.calculate_inverse_dynamics(ddq, dq, q)
|
||||
|
||||
# get linear jacobian
|
||||
Jlin = robot.get_linear_jacobian(link_id=link_id, local_position=com_frame)
|
||||
|
||||
# attractor point: compute cartesian forces (PD control)
|
||||
F = K.dot(x_des - x) - D.dot(dx)
|
||||
|
||||
# add torques resulting from them
|
||||
torques += Jlin.T.dot(F)
|
||||
# torques += Jlin.T.dot(- D.dot(dx)) # active compliance
|
||||
# torques = Jlin.T.dot(F)
|
||||
|
||||
# impedance control
|
||||
robot.set_joint_torques(torques=torques)
|
||||
|
||||
# perform a step in the world
|
||||
world.step(sleep_dt=1./240)
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
"""Force control: gravity compensation with RRBot
|
||||
|
||||
Try to move the end-effector using the mouse, and see what happens. Compare the obtained results with
|
||||
`force/no_forces.py` and `impedance/attractor_point.py`.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from itertools import count
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# Create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create world
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load robot
|
||||
robot = prl.robots.RRBot(sim)
|
||||
robot.disable_motor() # disable motors; comment the `robot.set_joint_torques(torques)` to see what happens
|
||||
robot.print_info()
|
||||
robot.change_transparency()
|
||||
|
||||
|
||||
# run simulator
|
||||
for _ in count():
|
||||
# get current joint positions, velocities, accelerations
|
||||
q = robot.get_joint_positions()
|
||||
dq = robot.get_joint_velocities()
|
||||
ddq = np.zeros(len(q))
|
||||
|
||||
# compute torques (Coriolis, centrifugal and gravity compensation) using inverse dynamics
|
||||
torques = robot.calculate_inverse_dynamics(ddq, dq, q)
|
||||
|
||||
# force control
|
||||
robot.set_joint_torques(torques=torques)
|
||||
|
||||
# perform a step in the world
|
||||
world.step(sleep_dt=sim.dt)
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
"""Force control: apply no forces/torques.
|
||||
|
||||
Try to move the end-effector using the mouse, and see what happens. Compare the obtained results with
|
||||
`force/gravity_compensation.py` and `impedance/attractor_point.py`.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from itertools import count
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# Create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create world
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load robot
|
||||
robot = prl.robots.RRBot(sim)
|
||||
robot.disable_motor() # disable motors
|
||||
robot.print_info()
|
||||
robot.change_transparency()
|
||||
|
||||
|
||||
# run simulator
|
||||
for _ in count():
|
||||
|
||||
# force control: apply no forces/torques
|
||||
robot.set_joint_torques(torques=np.zeros(len(robot.joints)))
|
||||
|
||||
# perform a step in the world
|
||||
world.step(sleep_dt=sim.dt)
|
||||
@@ -0,0 +1,92 @@
|
||||
Environments
|
||||
============
|
||||
|
||||
In this folder, we provide examples on how to define and use environments which are notably useful for imitation and reinforcement learning.
|
||||
|
||||
An environment is defined as the following figures (inspired by [1]_):
|
||||
|
||||
.. image:: ../../docs/figures/environment.png
|
||||
:alt: environment
|
||||
:align: center
|
||||
|
||||
In PRL, the environment is an abstraction layer class that regroups:
|
||||
|
||||
- the world; an instance of ``World`` which will be used to perform a step in the world (simulator). This is called at each step performed by the environment.
|
||||
- the states: an instance of ``State`` (or a list of them). The states are updated at each time step by the environment.
|
||||
- the rewards (optional): an instance of ``Reward`` (or a list of them). It is optional because some environments like in imitation learning does not require a reward function. The reward functions are computed at each time step.
|
||||
- the terminal conditions (optional): an instance of ``TerminalCondition`` (or a list of them) that checks at each time step if the goal of the environment has been achieved. A ``TerminalCondition`` also details if the environment ended with a success or failure.
|
||||
- the initial state generators (optional): an instance of ``StateGenerator`` (or a list of them) which are called to generate the initial states each time the environment is reset.
|
||||
- the physics randomizers (optional): an instance of ``PhysicsRandomizer`` (or a list of them) to randomize the physical properties of bodies in the simulator, or the simulator itself, each time the environment is reset.
|
||||
- the actions (optional): an instance of ``Action`` (or a list of them). The actions are not used nor updated by the environment. This is left to the ``Policy`` or ``Controller``.
|
||||
|
||||
|
||||
By favoring `composition over inheritance <https://en.wikipedia.org/wiki/Composition_over_inheritance>`_ for the environment class, we improve the flexibility of the framework and the reuse of different modules.
|
||||
This leads ultimately to less code duplication, and ease the process of creating environments.
|
||||
|
||||
Here is a short snippet showing the basic usage of an environment:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
# define the simulator and world (and load what you want in it)
|
||||
sim = ...
|
||||
world = ...
|
||||
robot = ...
|
||||
|
||||
# define state, action, and reward (and possibly action)
|
||||
state = ...
|
||||
action = ...
|
||||
reward = ...
|
||||
|
||||
# you can give the reward function to your RL environment
|
||||
# which will use it when calling `env.step()`.
|
||||
env = prl.envs.Env(world, state, reward)
|
||||
|
||||
# like in OpenAI gym environments, you can reset and step in the environment
|
||||
obs = env.reset()
|
||||
for t in count():
|
||||
obs, rew, done, info = env.step()
|
||||
|
||||
|
||||
Few notes regarding the code above:
|
||||
|
||||
- the ``action`` can also be given to the environment but it won't be called by the environment. This is carried out by the policy(ies)/agent(s). The main reason why you can give an action to an environment is when later you will create your own environment class (that inherits from ``prl.envs.Env``), you will be able to get the states and actions for your policies in the following way:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
# define your environment
|
||||
class MyEnv(prl.envs.Env):
|
||||
...
|
||||
|
||||
# create the environment and provide possible arguments
|
||||
env = MyEnv(args)
|
||||
|
||||
# get states and actions from your environment
|
||||
states, actions = env.states, env.actions
|
||||
|
||||
# create policy
|
||||
policy = Policy(states, actions)
|
||||
|
||||
- the observation ``obs`` is a list of arrays that are returned by the environment. This is a bit different from what it is usually returned by gym environments (which is an array). The reason is that the states returned by the environment might have different dimensions (e.g. joint positions = 1D array, camera = 2D/3D array, etc) so you can not return one array.
|
||||
- You can easily update the state, reward function, world, and other modules that are given to environment. This results in less code duplication and greater flexibility.
|
||||
|
||||
|
||||
For more info, please check the documentation.
|
||||
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
|
||||
Here are few examples that you can find in this folder that better demonstrate how to use the environment:
|
||||
|
||||
1. ``basics.py``: show the flexibility of how to build an environment and use it.
|
||||
2. ``manipulator.py``: show how to define an environment where the goal is to reach a target object using a manipulator.
|
||||
|
||||
References:
|
||||
|
||||
.. [1] "Reinforcement Learning: An Introduction", Sutton and Barto, 1998
|
||||
@@ -1,4 +1,17 @@
|
||||
## Interfaces
|
||||
## Interfaces and Bridges
|
||||
|
||||
In this folder, you will find examples on what interfaces you can use and on how you can collect the data from them.
|
||||
You will also be able to connect an interface with an element of the world (in this case, a robot) using bridges, and see that different bridges can lead to different behaviors while getting the data from the same interface.
|
||||
You will also be able to connect an interface with an element of the world (in this case, a robot) using bridges,
|
||||
and see that different bridges can lead to different behaviors while getting the data from the same interface.
|
||||
|
||||
Here are few examples that depict the various interfaces available to the user:
|
||||
1. `mouse_keyboard.py`: use the mouse keyboard interface
|
||||
2. `webcam.py`: use the webcam interface
|
||||
3. `playstation.py`: use the Playstation game controller interface
|
||||
4. `xbox.py`: use the Xbox game controller interface
|
||||
5. `asus_xtion.py`: use the Asus Xtion interface
|
||||
6. `openpose.py`: use the Openpose interface
|
||||
7. `speech.py`: use the speech (recognizer/translator) interface
|
||||
8. `spacemouse.py`: use the (3Dconnexion) SpaceMouse interface
|
||||
|
||||
**Note**: some interfaces require to install different libraries, and possibly to configure them. Check the raised errors.
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
"""Run the Asus Xtion interface.
|
||||
|
||||
Make sure that the `openni` library is installed with all the correct environment variables set, and that the Asus
|
||||
Xtion is connected before running this code. Note that it can take some time to initialize the interface.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from pyrobolearn.tools.interfaces.camera.asus_xtion import AsusXtionInterface
|
||||
|
||||
|
||||
# create parser
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-t', '--use_thread', help='If we should run the webcam interface in a thread.', type=bool,
|
||||
default=False)
|
||||
parser.add_argument('-r', '--use_rgb', help='If we should get RGB images. Note that RGB and IR images can not be '
|
||||
'captured at the same time.', type=bool,
|
||||
default=True)
|
||||
parser.add_argument('-d', '--use_depth', help='If we should get depth images.', type=bool,
|
||||
default=True)
|
||||
parser.add_argument('-i', '--use_ir', help='If we should get IR images. Note that RGB and IR images can not be '
|
||||
'captured at the same time.', type=bool,
|
||||
default=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# get which pictures to capture
|
||||
use_rgb, use_depth, use_ir = args.use_rgb, args.use_depth, args.use_ir
|
||||
if use_rgb and use_ir:
|
||||
use_ir = False
|
||||
|
||||
|
||||
# create Asus Xtion interface
|
||||
interface = AsusXtionInterface(use_rgb=use_rgb, use_depth=use_depth, use_ir=use_ir)
|
||||
|
||||
|
||||
# plotting using matplotlib in interactive mode
|
||||
fig, axes = plt.subplots(1, 2)
|
||||
plots = [None]*2
|
||||
titles = []
|
||||
if use_rgb:
|
||||
titles.append('RGB')
|
||||
if use_ir:
|
||||
titles.append('IR')
|
||||
if use_depth:
|
||||
titles.append('Depth')
|
||||
|
||||
plt.ion() # interactive mode on
|
||||
|
||||
while True:
|
||||
# if don't use thread call `step` or `run`
|
||||
data = interface.run()
|
||||
|
||||
# get the frame and plot it with matplotlib
|
||||
if plots[0] is None:
|
||||
for i in range(len(plots)):
|
||||
plots[i] = axes[i].imshow(data[i])
|
||||
axes[i].set_title(titles[i])
|
||||
else:
|
||||
for plot, img in zip(plots, data):
|
||||
plot.set_data(img)
|
||||
|
||||
# pause a bit
|
||||
plt.pause(0.01)
|
||||
|
||||
# check if the figure is closed, and if so, get out of the loop
|
||||
if not plt.fignum_exists(fig.number):
|
||||
break
|
||||
|
||||
plt.ioff() # interactive mode off
|
||||
plt.show()
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python
|
||||
"""Load the mouse keyboard interface.
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
|
||||
import pyrobolearn as prl
|
||||
from pyrobolearn.tools.interfaces.mouse_keyboard import MouseKeyboardInterface
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create mouse keyboard interface
|
||||
# Note that to give the simulator `sim` to the interface can be optional especially if there is only one simulator.
|
||||
# The interface will look in the memory to check the instantiated simulators and take the first one if it exists.
|
||||
interface = MouseKeyboardInterface(sim)
|
||||
|
||||
# run interface
|
||||
for _ in count():
|
||||
# perform a step with the interface
|
||||
interface.step()
|
||||
|
||||
# print pressed keys
|
||||
if len(interface.key_pressed) > 0:
|
||||
print("Keys that are pressed: {}".format(interface.key_pressed))
|
||||
if len(interface.key_down) > 0:
|
||||
print("Keys that are down: {}".format(interface.key_down))
|
||||
|
||||
# perform a step with the simulator
|
||||
sim.step(sleep_time=sim.dt)
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
"""Run the Openpose interface.
|
||||
|
||||
Make sure that the webcam is connected, and that the openpose framework has been installed before running this code.
|
||||
For this code to work, you have to specify the path to the openpose framework, or set the `OPENPOSE_PATH` environment
|
||||
variable. Note that it can take some time to initialize the interface.
|
||||
"""
|
||||
|
||||
import cv2
|
||||
import argparse
|
||||
|
||||
from pyrobolearn.tools.interfaces.camera.openpose import OpenPoseInterface
|
||||
|
||||
|
||||
# create parser
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-p', '--path', help='Absolute path to the openpose framework. If not specified, it will check '
|
||||
'for the environment variable `OPENPOSE_PATH`.', type=str, default='')
|
||||
parser.add_argument('-t', '--use_thread', help='If we should run the openpose interface in a thread.', type=bool,
|
||||
default=False)
|
||||
parser.add_argument('-f', '--detect_face', help='If we should detect the face with openpose.', type=bool,
|
||||
default=True)
|
||||
parser.add_argument('-a', '--detect_hands', help='If we should detect the hands with openpose.', type=bool,
|
||||
default=False)
|
||||
args = parser.parse_args()
|
||||
path = None if args.path == '' else args.path
|
||||
|
||||
|
||||
# create openpose interface
|
||||
if args.use_thread:
|
||||
# create and run interface in a thread
|
||||
interface = OpenPoseInterface(openpose_path=path, detect_face=args.detect_face, detect_hands=args.detect_hands,
|
||||
use_thread=True, sleep_dt=1. / 10, verbose=True)
|
||||
raw_input('Press key to stop the openpose interface')
|
||||
else:
|
||||
# create interface
|
||||
interface = OpenPoseInterface(openpose_path=path, detect_face=args.detect_face, detect_hands=args.detect_hands)
|
||||
|
||||
# run interface
|
||||
while True:
|
||||
frame, keypoints = interface.run()
|
||||
cv2.imshow("OpenPose 1.4.0 - Tutorial Python API", frame)
|
||||
|
||||
# quit display if 'esc' button is pressed
|
||||
key = cv2.waitKey(15) & 0xFF
|
||||
if key == 27:
|
||||
cv2.destroyWindow('frame')
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
"""Load the Playstation game controller interface
|
||||
|
||||
How to run:
|
||||
```
|
||||
$ python playstation.py --help # for help
|
||||
$ python playstation.py --controller ps # to use any PS game controller (by default)
|
||||
$ python playstation.py --controller ps3 # to use PS3 game controller
|
||||
$ python playstation.py --controller ps4 # to use PS4 game controller
|
||||
```
|
||||
|
||||
Note that these game controllers are blocking by default, thus set `use_thread` to True to avoid to be blocked.
|
||||
"""
|
||||
|
||||
import time
|
||||
import argparse
|
||||
|
||||
from pyrobolearn.tools.interfaces.controllers.playstation import *
|
||||
|
||||
|
||||
# create parser to select the game controller
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-t', '--use_thread', help='If we should run the PlayStation controller in a thread.', type=bool,
|
||||
default=True)
|
||||
parser.add_argument('-c', '--controller', help='The Playstation game controller to use (ps, ps3, or ps4)', type=str,
|
||||
choices=['ps', 'ps3', 'ps4'], default='ps')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# load corresponding Playstation controller interface
|
||||
if args.controller == 'ps':
|
||||
controller = PSControllerInterface(use_thread=args.use_thread, verbose=False)
|
||||
if args.controller == 'ps3':
|
||||
controller = PS3ControllerInterface(use_thread=args.use_thread, verbose=False)
|
||||
elif args.controller == 'ps4':
|
||||
controller = PS4ControllerInterface(use_thread=args.use_thread, verbose=False)
|
||||
else:
|
||||
raise NotImplementedError("Unknown game controller")
|
||||
|
||||
|
||||
# run controller
|
||||
print('Running controller...')
|
||||
while True:
|
||||
|
||||
# run one step with the interface
|
||||
controller.step() # same as `step()` if we are not using threads
|
||||
|
||||
# get the last update and print it
|
||||
b = controller.last_updated_button
|
||||
print("Last updated button: {} with value: {}".format(b, controller[b]))
|
||||
|
||||
# sleep a bit
|
||||
time.sleep(0.01)
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python
|
||||
"""Control a quadcopter in the air using an Xbox or Playstation game controller.
|
||||
|
||||
how to run:
|
||||
```
|
||||
$ python quadcopter_controller.py --help # for help
|
||||
$ python quadcopter_controller.py --controller keyboard # to use the keyboard
|
||||
$ python quadcopter_controller.py --controller xbox # to use Xbox game controller
|
||||
$ python quadcopter_controller.py --controller ps # to use PS game controller
|
||||
```
|
||||
|
||||
Mapping of the keyboard interface:
|
||||
- `top arrow`: move forward
|
||||
- `bottom arrow`: move backward
|
||||
- `left arrow`: move sideways to the left
|
||||
- `right arrow`: move sideways to the right
|
||||
- `ctrl + top arrow`: ascend
|
||||
- `ctrl + bottom arrow`: descend
|
||||
- `ctrl + left arrow`: turn to the right
|
||||
- `ctrl + right arrow`: turn to the left
|
||||
- `space`: switch between first-person and third-person view
|
||||
|
||||
Mapping between the controller and the quadcopter:
|
||||
- left joystick: use to move the quadcopter
|
||||
- right joystick: use to ascend/descend and turn
|
||||
- south button (X on PlayStation and A on Xbox): change between the first-person and third-person view.
|
||||
- east button (circle on PlayStation and B on Xbox): increase the speed
|
||||
- west button (square on PlayStation and X on Xbox): decrease the speed
|
||||
"""
|
||||
|
||||
# import numpy as np
|
||||
from itertools import count
|
||||
import argparse
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create parser to select the game controller
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-c', '--controller', help='the controller to use', type=str,
|
||||
choices=['keyboard', 'xbox', 'ps'], default='keyboard')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# load corresponding interface
|
||||
if args.controller == 'keyboard': # keyboard interface
|
||||
from pyrobolearn.tools.interfaces.mouse_keyboard.mousekeyboard import MouseKeyboardInterface as Controller
|
||||
from pyrobolearn.tools.bridges.mouse_keyboard.bridge_mousekeyboard_quadcopter \
|
||||
import BridgeMouseKeyboardQuadcopter as Bridge
|
||||
elif args.controller == 'xbox': # Xbox interface
|
||||
from pyrobolearn.tools.interfaces.controllers.xbox import XboxControllerInterface as Controller
|
||||
from pyrobolearn.tools.bridges.controllers.robots.bridge_controller_quadcopter import BridgeControllerQuadcopter \
|
||||
as Bridge
|
||||
elif args.controller == 'ps': # PS interface
|
||||
from pyrobolearn.tools.interfaces.controllers.playstation import PSControllerInterface as Controller
|
||||
from pyrobolearn.tools.bridges.controllers.robots.bridge_controller_quadcopter import BridgeControllerQuadcopter \
|
||||
as Bridge
|
||||
else:
|
||||
raise NotImplementedError("Unknown game controller")
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create basic world (with a floor and gravity enabled by default)
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load quadcopter
|
||||
robot = prl.robots.Quadcopter(sim, position=[0., 0., 2.])
|
||||
world.load_robot(robot)
|
||||
|
||||
# load interface that accepts input events
|
||||
controller = Controller(use_thread=True, verbose=False)
|
||||
|
||||
# load bridge that connects the interface/controller with the quadcopter
|
||||
# The bridge is the one that maps the input events from the interface to commands sent to the quadcopter
|
||||
bridge = Bridge(quadcopter=robot, interface=controller)
|
||||
|
||||
# run simulator
|
||||
for t in count():
|
||||
# perform a step with the bridge and interface
|
||||
bridge.step(update_interface=True)
|
||||
|
||||
# perform one step in the world
|
||||
world.step(sleep_dt=1. / 240)
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
"""Control a quadcopter in the air using speech.
|
||||
|
||||
Try to say:
|
||||
- turn right/left
|
||||
- move/go higher/lower/forward/backward/right/left
|
||||
- go faster/slower
|
||||
- anything else will ask the robot to hover
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
|
||||
import pyrobolearn as prl
|
||||
from pyrobolearn.tools.bridges.audio.robots.bridge_speech_quadcopter import BridgeSpeechRecognizerQuadcopter
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create basic world (with a floor and gravity enabled by default)
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load quadcopter
|
||||
robot = prl.robots.Quadcopter(sim, position=[0., 0., 2.])
|
||||
world.load_robot(robot)
|
||||
|
||||
# load bridge that connects the speech interface with the quadcopter
|
||||
# Note that it will create automatically the Speech Recognizer interface inside the bridge
|
||||
bridge = BridgeSpeechRecognizerQuadcopter(robot=robot, interface=None, verbose=True)
|
||||
|
||||
|
||||
# run simulator
|
||||
for t in count():
|
||||
# perform a step with the bridge and interface
|
||||
bridge.step(update_interface=True)
|
||||
|
||||
# ask the world camera to follow the wheeled robot
|
||||
world.follow(robot, distance=2)
|
||||
|
||||
# perform one step in the world
|
||||
world.step(sleep_dt=1. / 240)
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python
|
||||
"""Control a wheeled robot using a keyboard, an Xbox or Playstation game controller.
|
||||
|
||||
how to run:
|
||||
```
|
||||
$ python wheeled_controller.py --help # for help
|
||||
$ python wheeled_controller.py --controller keyboard # to use the keyboard
|
||||
$ python wheeled_controller.py --controller xbox # to use Xbox game controller
|
||||
$ python wheeled_controller.py --controller ps # to use PS game controller
|
||||
```
|
||||
|
||||
Mapping of the keyboard interface:
|
||||
* `top arrow`: move forward
|
||||
* `bottom arrow`: move backward
|
||||
* `left arrow`: turn/steer to the left
|
||||
* `right arrow`: turn/steer to the right
|
||||
|
||||
Mapping between the controller and the wheeled robot:
|
||||
- left joystick: velocity of the wheeled robot
|
||||
- east button (circle on PlayStation and B on Xbox): increase the speed
|
||||
- west button (square on PlayStation and X on Xbox): decrease the speed
|
||||
"""
|
||||
|
||||
# import numpy as np
|
||||
from itertools import count
|
||||
import argparse
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create parser to select the game controller
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-c', '--controller', help='the controller to use', type=str,
|
||||
choices=['keyboard', 'xbox', 'ps'], default='keyboard')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# load corresponding interface
|
||||
if args.controller == 'keyboard': # keyboard interface
|
||||
from pyrobolearn.tools.interfaces.mouse_keyboard.mousekeyboard import MouseKeyboardInterface as Controller
|
||||
from pyrobolearn.tools.bridges.mouse_keyboard.bridge_mousekeyboard_wheeled \
|
||||
import BridgeMouseKeyboardDifferentialWheeledRobot as Bridge
|
||||
elif args.controller == 'xbox': # Xbox interface
|
||||
from pyrobolearn.tools.interfaces.controllers.xbox import XboxControllerInterface as Controller
|
||||
from pyrobolearn.tools.bridges.controllers.robots.bridge_controller_wheeled import BridgeControllerWheeledRobot \
|
||||
as Bridge
|
||||
elif args.controller == 'ps': # PS interface
|
||||
from pyrobolearn.tools.interfaces.controllers.playstation import PSControllerInterface as Controller
|
||||
from pyrobolearn.tools.bridges.controllers.robots.bridge_controller_wheeled import \
|
||||
BridgeControllerWheeledRobot as Bridge
|
||||
else:
|
||||
raise NotImplementedError("Unknown game controller")
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create basic world (with a floor and gravity enabled by default)
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load wheeled robot
|
||||
robot = prl.robots.Epuck(sim, position=[0., 0.])
|
||||
world.load_robot(robot)
|
||||
|
||||
# load interface that accepts input events
|
||||
controller = Controller(use_thread=True, verbose=False)
|
||||
|
||||
# load bridge that connects the interface/controller with the quadcopter
|
||||
# The bridge is the one that maps the input events from the interface to commands sent to the quadcopter
|
||||
bridge = Bridge(robot=robot, interface=controller)
|
||||
|
||||
|
||||
# run simulator
|
||||
for t in count():
|
||||
# perform a step with the bridge and interface
|
||||
bridge.step(update_interface=True)
|
||||
|
||||
# perform one step in the world
|
||||
world.step(sleep_dt=1. / 240)
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
"""Control a wheeled robot in the air using speech.
|
||||
|
||||
Try to say:
|
||||
- turn right/left
|
||||
- move/go forward/backward
|
||||
- go faster/slower
|
||||
- anything else will ask the robot to hover
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
|
||||
import pyrobolearn as prl
|
||||
from pyrobolearn.tools.bridges.audio.robots.bridge_speech_wheeled import BridgeSpeechRecognizerDifferentialWheeledRobot
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create basic world (with a floor and gravity enabled by default)
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load wheeled robot
|
||||
robot = prl.robots.Epuck(sim, position=[0., 0.])
|
||||
world.load_robot(robot)
|
||||
|
||||
# load bridge that connects the speech interface with the wheeled robot
|
||||
# Note that it will create automatically the Speech Recognizer interface inside the bridge
|
||||
bridge = BridgeSpeechRecognizerDifferentialWheeledRobot(robot=robot, interface=None, verbose=True)
|
||||
|
||||
|
||||
# run simulator
|
||||
for t in count():
|
||||
# perform a step with the bridge and interface
|
||||
bridge.step(update_interface=True)
|
||||
|
||||
# ask the world camera to follow the wheeled robot
|
||||
world.follow(robot, distance=2)
|
||||
|
||||
# perform one step in the world
|
||||
world.step(sleep_dt=1. / 240)
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
"""Run the Space mouse interface.
|
||||
|
||||
Make sure that the `spnav` library is installed, and the space mouse (by 3Dconnexion) is connected to the computer
|
||||
before running this code.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import time
|
||||
|
||||
from pyrobolearn.tools.interfaces.mouse_keyboard.spacemouse import SpaceMouseInterface
|
||||
|
||||
|
||||
# create parser
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-t', '--use_thread', help='If we should run the webcam interface in a thread.', type=bool,
|
||||
default=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# create webcam interface
|
||||
if args.use_thread:
|
||||
# create and run interface in a thread
|
||||
interface = SpaceMouseInterface(use_thread=True, sleep_dt=0.001, verbose=True)
|
||||
raw_input('Press key to stop the space mouse interface')
|
||||
else:
|
||||
# create interface
|
||||
interface = SpaceMouseInterface(use_thread=False, verbose=True)
|
||||
|
||||
while True:
|
||||
# perform a `step` with the interface
|
||||
interface.step()
|
||||
time.sleep(0.001)
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
"""Run the speech interface.
|
||||
|
||||
This will perform speech recognition, translation, and synthesization. Make sure that your computer has a microphone
|
||||
connected.
|
||||
|
||||
In the future, interfaces using the Google assistant, Alexa, or a similar tool will be implemented.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
|
||||
from pyrobolearn.tools.interfaces.audio.speech import SpeechRecognizerInterface, SpeechTranslatorInterface
|
||||
|
||||
|
||||
# get the available languages.
|
||||
languages = SpeechRecognizerInterface.available_languages
|
||||
print("Available languages are: {}".format(languages))
|
||||
|
||||
# create parser
|
||||
parser = argparse.ArgumentParser()
|
||||
# parser.add_argument('-t', '--use_thread', help='If we should run the webcam interface in a thread.', type=bool,
|
||||
# default=False)
|
||||
parser.add_argument('-l', '--lang', help='The language that needs to be recognized.', type=str, choices=languages,
|
||||
default='english')
|
||||
parser.add_argument('-a', '--target_lang', help='If we should get depth images.', type=str, choices=languages,
|
||||
default='english')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# create speech recognizer/translator interface
|
||||
# interface = SpeechRecognizerInterface(verbose=True, lang=args.lang)
|
||||
interface = SpeechTranslatorInterface(verbose=True, from_lang=args.lang, target_lang=args.target_lang)
|
||||
|
||||
# run the interface
|
||||
while True:
|
||||
data = interface.step()
|
||||
@@ -1,34 +1,52 @@
|
||||
#!/usr/bin/env python
|
||||
"""Load the Webcam interface.
|
||||
"""Run the Webcam interface.
|
||||
|
||||
Make sure that the webcam is connected before running this code. Note that it can take some time to initialize
|
||||
the interface.
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
import argparse
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from pyrobolearn.tools.interfaces.camera.webcam import WebcamInterface
|
||||
|
||||
# create interface
|
||||
interface = WebcamInterface(use_thread=True, sleep_dt=1./10, verbose=False)
|
||||
|
||||
# plotting using matplotlib in interactive mode
|
||||
fig = plt.figure()
|
||||
plot = None
|
||||
plt.ion() # interactive mode on
|
||||
# create parser
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-t', '--use_thread', help='If we should run the webcam interface in a thread.', type=bool,
|
||||
default=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
for _ in count():
|
||||
# # if don't use thread call `step` or `run` (note that `run` returns the frame but not
|
||||
# interface.step()
|
||||
|
||||
# get the frame and plot it with matplotlib
|
||||
frame = interface.frame
|
||||
if plot is None:
|
||||
plot = plt.imshow(frame)
|
||||
else:
|
||||
plot.set_data(frame)
|
||||
plt.pause(0.01)
|
||||
# create webcam interface
|
||||
if args.use_thread:
|
||||
# create and run interface in a thread
|
||||
interface = WebcamInterface(use_thread=True, sleep_dt=1./10, verbose=True)
|
||||
raw_input('Press key to stop the webcam interface')
|
||||
else:
|
||||
# create interface
|
||||
interface = WebcamInterface()
|
||||
|
||||
# check if the figure is closed, and if so, get out of the loop
|
||||
if not plt.fignum_exists(fig.number):
|
||||
break
|
||||
# plotting using matplotlib in interactive mode
|
||||
fig = plt.figure()
|
||||
plot = None
|
||||
plt.ion() # interactive mode on
|
||||
|
||||
plt.ioff() # interactive mode off
|
||||
plt.show()
|
||||
while True:
|
||||
# perform a `step` with the interface
|
||||
interface.step()
|
||||
|
||||
# get the frame and plot it with matplotlib
|
||||
frame = interface.frame
|
||||
if plot is None:
|
||||
plot = plt.imshow(frame)
|
||||
else:
|
||||
plot.set_data(frame)
|
||||
plt.pause(0.01)
|
||||
|
||||
# check if the figure is closed, and if so, get out of the loop
|
||||
if not plt.fignum_exists(fig.number):
|
||||
break
|
||||
|
||||
plt.ioff() # interactive mode off
|
||||
plt.show()
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python
|
||||
"""Load the Xbox game controller interface
|
||||
|
||||
How to run:
|
||||
```
|
||||
$ python xbox.py --help # for help
|
||||
$ python xbox.py --controller xbox # to use any Xbox game controller (by default)
|
||||
$ python xbox.py --controller xbox-360 # to use Xbox 360 game controller
|
||||
$ python xbox.py --controller xbox-one # to use Xbox One game controller
|
||||
```
|
||||
|
||||
Note that these game controllers are blocking by default, thus set `use_thread` to True to avoid to be blocked.
|
||||
"""
|
||||
|
||||
import time
|
||||
import argparse
|
||||
|
||||
from pyrobolearn.tools.interfaces.controllers.xbox import XboxControllerInterface, XboxOneControllerInterface, \
|
||||
Xbox360ControllerInterface
|
||||
|
||||
|
||||
# create parser to select the game controller
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-t', '--use_thread', help='If we should run the Xbox controller in a thread.', type=bool,
|
||||
default=True)
|
||||
parser.add_argument('-c', '--controller', help='The Xbox game controller to use.', type=str,
|
||||
choices=['xbox', 'xbox-360', 'xbox-one'], default='xbox')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# load corresponding Xbox controller interface
|
||||
if args.controller == 'xbox':
|
||||
controller = XboxControllerInterface(use_thread=args.use_thread, verbose=False)
|
||||
elif args.controller == 'xbox-360':
|
||||
controller = Xbox360ControllerInterface(use_thread=args.use_thread, verbose=False)
|
||||
elif args.controller == 'xbox-one':
|
||||
controller = XboxOneControllerInterface(use_thread=args.use_thread, verbose=False)
|
||||
else:
|
||||
raise NotImplementedError("Unknown game controller")
|
||||
|
||||
|
||||
# run controller
|
||||
print('Running controller...')
|
||||
while True:
|
||||
|
||||
# run one step with the interface
|
||||
controller.step()
|
||||
|
||||
# get the last update and print it
|
||||
b = controller.last_updated_button
|
||||
print("Last updated button: {} with value: {}".format(b, controller[b]))
|
||||
|
||||
# sleep a bit
|
||||
time.sleep(0.01)
|
||||
@@ -2,6 +2,19 @@
|
||||
|
||||
We provide examples on how to perform forward and inverse kinematics.
|
||||
|
||||
Here are the forward kinematics (FK) examples that the user can try:
|
||||
1. `fk.py`: simple forward kinematics example where we directly sent desired joint positions to the Kuka
|
||||
manipulator.
|
||||
|
||||
Here are the inverse kinematics (IK) examples that the user can try:
|
||||
1. `ik.py`: simple inverse kinematics example where the Kuka manipulator has to reach a certain target position
|
||||
in the world. In this example, the user can also choose the damped-least-squares IK solver.
|
||||
2. `ik_libraries.py`: comparison between different IK libraries including `pybullet`, `PyKDL`, `trac_ik`, and
|
||||
`rbdl` using the Kuka manipulator.
|
||||
3. `moving_sphere.py`: damped-least-squares IK with the Kuka manipulator where the goal is to follow a sphere
|
||||
that moves in a circular manner.
|
||||
|
||||
|
||||
References:
|
||||
- [1] "Robotics: Modelling, Planning and Control", Siciliano et al., 2010
|
||||
- [2] "Springer Handbook of Robotics", Siciliano et al., 2008
|
||||
|
||||
@@ -43,7 +43,7 @@ sphere = Body(sim, body_id=sphere)
|
||||
for t in count():
|
||||
|
||||
# if no more joint positions, get out of the loop
|
||||
if t > len(positions):
|
||||
if t >= len(positions):
|
||||
break
|
||||
|
||||
# set joint positions
|
||||
|
||||
@@ -8,16 +8,25 @@ Set the `solver_flag` to a number between 0 and 1 (see lines [19,22]) to select
|
||||
|
||||
import numpy as np
|
||||
from itertools import count
|
||||
import argparse
|
||||
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import KukaIIWA
|
||||
|
||||
|
||||
# create parser to select the IK solver
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-s', '--solver', help='the IK solver to select (0: use robot.calculate_inverse_kinematics(), '
|
||||
'1: use damped-least-squares IK using Jacobian)', type=int,
|
||||
choices=[0, 1], default=1)
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# select IK solver, by setting the flag:
|
||||
# 0 = pybullet + calculate_inverse_kinematics()
|
||||
# 1 = pybullet + damped-least-squares IK using Jacobian (provided by pybullet)
|
||||
solver_flag = 1 # 1 and 4 gives pretty good results
|
||||
solver_flag = args.solver # 1 gives a pretty good result
|
||||
|
||||
|
||||
# Create simulator
|
||||
@@ -34,6 +43,7 @@ robot.print_info()
|
||||
dt = 1./240
|
||||
link_id = robot.get_end_effector_ids(end_effector=0)
|
||||
joint_ids = robot.joints # actuated joint
|
||||
# joint_ids = joint_ids[2:]
|
||||
damping = 0.01 # for damped-least-squares IK
|
||||
wrt_link_id = -1 # robot.get_link_ids('iiwa_link_1')
|
||||
|
||||
@@ -41,11 +51,10 @@ wrt_link_id = -1 # robot.get_link_ids('iiwa_link_1')
|
||||
xd = np.array([0.5, 0., 0.5])
|
||||
world.load_visual_sphere(xd, radius=0.05, color=(1, 0, 0, 0.5))
|
||||
|
||||
# joint_ids = joint_ids[2:]
|
||||
|
||||
# change the robot visual
|
||||
robot.change_transparency()
|
||||
robot.draw_link_frames([-1, 0])
|
||||
robot.draw_bounding_boxes(joint_ids[0])
|
||||
robot.draw_link_frames(link_ids=[-1, 0])
|
||||
robot.draw_bounding_boxes(link_ids=joint_ids[0])
|
||||
# robot.draw_link_coms([-1,0])
|
||||
|
||||
qIdx = robot.get_q_indices(joint_ids)
|
||||
|
||||
@@ -14,40 +14,23 @@ Set the `solver_flag` to a number between 0 and 4 (see lines [53,60]) to select
|
||||
import os
|
||||
import numpy as np
|
||||
from itertools import count
|
||||
import argparse
|
||||
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import KukaIIWA
|
||||
|
||||
|
||||
# import PyKDL
|
||||
try:
|
||||
import PyKDL as kdl
|
||||
except ImportError as e:
|
||||
raise ImportError(repr(e) + '\nTry to install `PyKDL`: '
|
||||
'sudo apt-get install ros-<distribution>-python-orocos-kdl'
|
||||
'or install it manually from `https://github.com/orocos/orocos_kinematics_dynamics`')
|
||||
|
||||
# import kdl_parser_py
|
||||
try:
|
||||
import kdl_parser_py.urdf as KDLParser
|
||||
except ImportError as e:
|
||||
raise ImportError(repr(e) + '\nTry to install `kdl_parser_py`: '
|
||||
'sudo apt-get install ros-<distribution>-kdl-parser-py')
|
||||
|
||||
# import track_ik_python
|
||||
try:
|
||||
from trac_ik_python.trac_ik import IK as TracIK
|
||||
except ImportError as e:
|
||||
raise ImportError(repr(e) + '\nTry to install `trac_ik_python`: '
|
||||
'sudo apt-get install ros-<distribution>-trac-ik-python')
|
||||
|
||||
# import rbdl
|
||||
try:
|
||||
import rbdl
|
||||
except ImportError as e:
|
||||
raise ImportError(repr(e) + '\nTry to install `rbdl` manually from `https://bitbucket.org/rbdl/rbdl`')
|
||||
|
||||
# create parser to select the IK solver
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-s', '--solver', help='the IK solver to select:\n'
|
||||
'0: use robot.calculate_inverse_kinematics()\n'
|
||||
'1: use damped-least-squares IK using Jacobian (provided by simulator)\n'
|
||||
'2: use PyKDL\n'
|
||||
'3: use trac_ik\n'
|
||||
'4: use rbdl + damped-least-squares IK using Jacobian (provided by rbdl)',
|
||||
type=int, choices=[0, 1, 2, 3, 4], default=1)
|
||||
args = parser.parse_args()
|
||||
|
||||
# TO BE SET BY THE USER
|
||||
# select IK solver, by setting the flag:
|
||||
@@ -56,7 +39,39 @@ except ImportError as e:
|
||||
# 2 = PyKDL
|
||||
# 3 = trac_ik
|
||||
# 4 = rbdl + damped-least-squares IK using Jacobian (provided by rbdl)
|
||||
solver_flag = 1 # 1 and 4 gives pretty good results
|
||||
solver_flag = args.solver # 1 and 4 gives pretty good results
|
||||
|
||||
if solver_flag == 2: # PyKDL
|
||||
# import PyKDL
|
||||
try:
|
||||
import PyKDL as kdl
|
||||
except ImportError as e:
|
||||
raise ImportError(repr(e) + '\nTry to install `PyKDL`: '
|
||||
'sudo apt-get install ros-<distribution>-python-orocos-kdl'
|
||||
'or install it manually from '
|
||||
'`https://github.com/orocos/orocos_kinematics_dynamics`')
|
||||
|
||||
# import kdl_parser_py
|
||||
try:
|
||||
import kdl_parser_py.urdf as kdl_parser
|
||||
except ImportError as e:
|
||||
raise ImportError(repr(e) + '\nTry to install `kdl_parser_py`: '
|
||||
'sudo apt-get install ros-<distribution>-kdl-parser-py')
|
||||
|
||||
elif solver_flag == 3: # trac_ik_python
|
||||
# import trac_ik_python
|
||||
try:
|
||||
from trac_ik_python.trac_ik import IK as trac_ik
|
||||
except ImportError as e:
|
||||
raise ImportError(repr(e) + '\nTry to install `trac_ik_python`: '
|
||||
'sudo apt-get install ros-<distribution>-trac-ik-python')
|
||||
|
||||
elif solver_flag == 4: # rbdl
|
||||
# import rbdl
|
||||
try:
|
||||
import rbdl
|
||||
except ImportError as e:
|
||||
raise ImportError(repr(e) + '\nTry to install `rbdl` manually from `https://bitbucket.org/rbdl/rbdl`')
|
||||
|
||||
|
||||
# Create simulator
|
||||
@@ -181,7 +196,7 @@ elif solver_flag == 1:
|
||||
##################
|
||||
elif solver_flag == 2:
|
||||
print("Using PyKDL:")
|
||||
model = KDLParser.treeFromFile(urdf)
|
||||
model = kdl_parser.treeFromFile(urdf)
|
||||
if model[0]:
|
||||
model = model[1]
|
||||
else:
|
||||
@@ -237,7 +252,7 @@ elif solver_flag == 3:
|
||||
urdf_string = open(urdf, 'r').read()
|
||||
|
||||
# create IK solver
|
||||
ik_solver = TracIK(base_link=base_name, tip_link=end_effector_name, urdf_string=urdf_string, solve_type='Distance')
|
||||
ik_solver = trac_ik(base_link=base_name, tip_link=end_effector_name, urdf_string=urdf_string, solve_type='Distance')
|
||||
|
||||
# define upper and lower limits (optional)
|
||||
# lb, ub = -np.ones(6)*100, np.ones(6)*100
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
"""Draw the 2D velocity and force manipulability ellipsoids on the end-effector of a 3-link planar manipulator.
|
||||
|
||||
References:
|
||||
[1] "Robotics: Modelling, Planning and Control" (section 3.9), Siciliano et al., 2010
|
||||
"""
|
||||
|
||||
import time
|
||||
# from itertools import count
|
||||
import numpy as np
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create world
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# create robot
|
||||
robot = world.load_robot('manipulator2d')
|
||||
robot.reset_joint_states(q=[0.64453457, -1.65045902, -0.31141744])
|
||||
|
||||
# change camera view
|
||||
world.camera.reset(distance=2, yaw=-np.pi / 2, pitch=-np.pi/2.01)
|
||||
|
||||
# draw 2d velocity manipulability ellipsoid
|
||||
# print(robot.end_effector_names)
|
||||
end_effector_id = robot.get_link_ids('gripper')
|
||||
jacobian = robot.get_linear_jacobian(link_id=end_effector_id)
|
||||
jjt = robot.get_JJT(jacobian)
|
||||
robot.draw_velocity_manipulability_ellipsoid(link_id=end_effector_id, JJT=jjt, color=(0, 1, 0, 0.7)) # green
|
||||
robot.draw_force_manipulability_ellipsoid(link_id=end_effector_id, JJT=jjt, color=(1, 0, 0, 0.7)) # red
|
||||
|
||||
# TODO: fix bug
|
||||
|
||||
time.sleep(10000)
|
||||
# run simulator
|
||||
# for t in count():
|
||||
# world.step(sleep_dt=1./240)
|
||||
@@ -2,6 +2,16 @@
|
||||
|
||||
We provide examples on how to use manipulability ellipsoids.
|
||||
|
||||
Here are a short description of the various examples the user can try:
|
||||
1. `2d_manipulability.py`: draw the 2D velocity and force manipulability ellipsoids on the end-effector of a
|
||||
3-link planar manipulator.
|
||||
2. `com_manipulability_tracking.py`: track the velocity manipulability ellipsoid of the center of mass of a robot
|
||||
with a fixed base.
|
||||
3. `com_manipulability_tracking_with_balance.py`: track the velocity manipulability ellipsoid of the center of mass
|
||||
of a floating-base robot while keeping its balance.
|
||||
4. `com_dynamic_manipulability_tracking_with_balance.py`: track the dynamic manipulability ellipsoid of the center
|
||||
of mass of a floating-base robot while keeping its balance.
|
||||
|
||||
References:
|
||||
- [1] "Robotics: Modelling, Planning and Control", Siciliano et al., 2010
|
||||
- [2] "Springer Handbook of Robotics", Siciliano et al., 2008
|
||||
|
||||
@@ -185,13 +185,13 @@ CoMr = robot.get_center_of_mass_position() # Desired CoM
|
||||
print("CoMr: {}".format(CoMr))
|
||||
|
||||
if robot.name == 'centauro':
|
||||
xref_l1f = robot.get_link_frame_world_positions(left_foot1_id) # Desired position for left foot
|
||||
xref_r1f = robot.get_link_frame_world_positions(right_foot1_id) # Desired position for right foot
|
||||
xref_l2f = robot.get_link_frame_world_positions(left_foot2_id) # Desired position for left foot
|
||||
xref_r2f = robot.get_link_frame_world_positions(right_foot2_id) # Desired position for right foot
|
||||
xref_l1f = robot.get_link_world_frame_positions(left_foot1_id) # Desired position for left foot
|
||||
xref_r1f = robot.get_link_world_frame_positions(right_foot1_id) # Desired position for right foot
|
||||
xref_l2f = robot.get_link_world_frame_positions(left_foot2_id) # Desired position for left foot
|
||||
xref_r2f = robot.get_link_world_frame_positions(right_foot2_id) # Desired position for right foot
|
||||
else:
|
||||
xref_lf = robot.get_link_frame_world_positions(left_foot_id) # Desired position for left foot
|
||||
xref_rf = robot.get_link_frame_world_positions(right_foot_id) # Desired position for right foot
|
||||
xref_lf = robot.get_link_world_frame_positions(left_foot_id) # Desired position for left foot
|
||||
xref_rf = robot.get_link_world_frame_positions(right_foot_id) # Desired position for right foot
|
||||
|
||||
|
||||
# Display initial and desired manipulability ellipsoid
|
||||
@@ -220,13 +220,13 @@ for i in range(num_samples):
|
||||
robot.draw_com_position(0.03)
|
||||
|
||||
if robot.name == 'centauro':
|
||||
xt_l1f = robot.get_link_frame_world_positions(left_foot1_id) # Current position for left foot
|
||||
xt_r1f = robot.get_link_frame_world_positions(right_foot1_id) # Current position for right foot
|
||||
xt_l2f = robot.get_link_frame_world_positions(left_foot2_id) # Current position for left foot
|
||||
xt_r2f = robot.get_link_frame_world_positions(right_foot2_id) # Current position for right foot
|
||||
xt_l1f = robot.get_link_world_frame_positions(left_foot1_id) # Current position for left foot
|
||||
xt_r1f = robot.get_link_world_frame_positions(right_foot1_id) # Current position for right foot
|
||||
xt_l2f = robot.get_link_world_frame_positions(left_foot2_id) # Current position for left foot
|
||||
xt_r2f = robot.get_link_world_frame_positions(right_foot2_id) # Current position for right foot
|
||||
else:
|
||||
xt_lf = robot.get_link_frame_world_positions(left_foot_id) # Current left foot pos
|
||||
xt_rf = robot.get_link_frame_world_positions(right_foot_id) # Current right foot pos
|
||||
xt_lf = robot.get_link_world_frame_positions(left_foot_id) # Current left foot pos
|
||||
xt_rf = robot.get_link_world_frame_positions(right_foot_id) # Current right foot pos
|
||||
|
||||
# Simple balance control with IK kinematics for CoM and feet
|
||||
# Get Jacobians: Jcom, Jlf, and Jrf
|
||||
|
||||
@@ -181,15 +181,15 @@ CoMr = robot.get_center_of_mass_position() # Desired CoM
|
||||
print("CoMr: {}".format(CoMr))
|
||||
|
||||
if robot.name == 'centauro':
|
||||
xref_l1f = robot.get_link_frame_world_positions(left_foot1_id) # Desired position for left foot
|
||||
xref_r1f = robot.get_link_frame_world_positions(right_foot1_id) # Desired position for right foot
|
||||
xref_l2f = robot.get_link_frame_world_positions(left_foot2_id) # Desired position for left foot
|
||||
xref_r2f = robot.get_link_frame_world_positions(right_foot2_id) # Desired position for right foot
|
||||
xref_l1f = robot.get_link_world_frame_positions(left_foot1_id) # Desired position for left foot
|
||||
xref_r1f = robot.get_link_world_frame_positions(right_foot1_id) # Desired position for right foot
|
||||
xref_l2f = robot.get_link_world_frame_positions(left_foot2_id) # Desired position for left foot
|
||||
xref_r2f = robot.get_link_world_frame_positions(right_foot2_id) # Desired position for right foot
|
||||
else:
|
||||
xref_lf = robot.get_link_frame_world_positions(left_foot_id) # Desired position for left foot
|
||||
# Qref_lf = robot.get_link_frame_world_orientations(leftFootId)
|
||||
xref_rf = robot.get_link_frame_world_positions(right_foot_id) # Desired position for right foot
|
||||
# Qref_rf = robot.get_link_frame_world_orientations(rightFootId)
|
||||
xref_lf = robot.get_link_world_frame_positions(left_foot_id) # Desired position for left foot
|
||||
# Qref_lf = robot.get_link_world_frame_orientations(leftFootId)
|
||||
xref_rf = robot.get_link_world_frame_positions(right_foot_id) # Desired position for right foot
|
||||
# Qref_rf = robot.get_link_world_frame_orientations(rightFootId)
|
||||
|
||||
|
||||
# Display initial and desired manipulability ellipsoid
|
||||
@@ -221,14 +221,14 @@ for i in range(400):
|
||||
robot.draw_com_position(0.03)
|
||||
|
||||
if robot.name == 'centauro':
|
||||
xt_l1f = robot.get_link_frame_world_positions(left_foot1_id) # Current position for left foot
|
||||
xt_r1f = robot.get_link_frame_world_positions(right_foot1_id) # Current position for right foot
|
||||
xt_l2f = robot.get_link_frame_world_positions(left_foot2_id) # Current position for left foot
|
||||
xt_r2f = robot.get_link_frame_world_positions(right_foot2_id) # Current position for right foot
|
||||
xt_l1f = robot.get_link_world_frame_positions(left_foot1_id) # Current position for left foot
|
||||
xt_r1f = robot.get_link_world_frame_positions(right_foot1_id) # Current position for right foot
|
||||
xt_l2f = robot.get_link_world_frame_positions(left_foot2_id) # Current position for left foot
|
||||
xt_r2f = robot.get_link_world_frame_positions(right_foot2_id) # Current position for right foot
|
||||
else:
|
||||
xt_lf = robot.get_link_frame_world_positions(left_foot_id) # Current left foot pos
|
||||
# Qt_lf = robot.get_link_frame_world_orientations(leftFootId)
|
||||
xt_rf = robot.get_link_frame_world_positions(right_foot_id) # Current right foot pos
|
||||
xt_lf = robot.get_link_world_frame_positions(left_foot_id) # Current left foot pos
|
||||
# Qt_lf = robot.get_link_world_frame_orientations(leftFootId)
|
||||
xt_rf = robot.get_link_world_frame_positions(right_foot_id) # Current right foot pos
|
||||
|
||||
# Simple balance control with IK kinematics for CoM and feet
|
||||
# Get Jacobians: Jcom, Jlf, and Jrf
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
Rewards
|
||||
=======
|
||||
|
||||
In this folder, we provide examples on how to use reward/cost functions which are provided to reinforcement learning environments.
|
||||
We show the available operations you can use on these.
|
||||
|
||||
The reward function might be defined as [1]_:
|
||||
|
||||
- :math:`r: \mathcal{S} \rightarrow \mathbb{R}`: given the state :math:`s \in \mathcal{S}`, it returns the reward value :math:`r(s)`.
|
||||
- :math:`r: \mathcal{S} \times \mathcal{A} \rightarrow \mathbb{R}`: given the state :math:`s \in \mathcal{S}` and action :math:`a \in \mathcal{A}`, it returns the reward value :math:`r(s,a)`.
|
||||
- :math:`r: \mathcal{S} \times \mathcal{A} \times \mathcal{S} \rightarrow \mathbb{R}`: given the state :math:`s \in \mathcal{S}`, action :math:`a \in \mathcal{A}`, and next state :math:`s' \in \mathcal{S}`, it returns the reward value :math:`r(s,a,s')`.
|
||||
|
||||
Note that the cost function is just minus the reward function, i.e. it is given by :math:`c(s,a,s') = -r(s,a,s')`.
|
||||
|
||||
In PRL, all reward functions inherit from the abstract ``Reward`` class defined in `pyrobolearn/rewards/reward.py <https://github.com/robotlearn/pyrobolearn/tree/master/pyrobolearn/rewards>`_, and several methods and operations are provided.
|
||||
You can for instance:
|
||||
|
||||
* provide the ``State`` and/or ``Action`` instances to some reward functions that will compute the reward value based on their value.
|
||||
* access to the range of the reward function.
|
||||
* add, multiply, divide, subtract, and apply basic functions such as :math:`\exp`, :math:`\cos`, :math:`\sin`, and others on reward functions. The resulting range is automatically scaled based on the operations.
|
||||
* define your own rewards/costs and reuse them in your code.
|
||||
|
||||
Here is a short snippet showing the basic usage of reward functions:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
import pyrobolearn as prl
|
||||
from pyrobolearn.rewards import FixedReward, YourReward
|
||||
|
||||
# define the simulator and world (and load what you want in it)
|
||||
sim = ...
|
||||
world = ...
|
||||
...
|
||||
|
||||
# define your state / action for your reward function
|
||||
state = ...
|
||||
action = ...
|
||||
|
||||
# define the reward function
|
||||
reward = 2 * FixedReward(3) + 0.5 * YourReward(state, action)
|
||||
|
||||
# print the range of the reward function
|
||||
print(reward.range)
|
||||
|
||||
# compute the reward value
|
||||
value = reward()
|
||||
print(value)
|
||||
|
||||
# update the state for instance
|
||||
state() # this will modify the internal state data
|
||||
|
||||
# recompute the reward value
|
||||
value = reward()
|
||||
print(value) # you will normally get a different value
|
||||
|
||||
# you can give the reward function to your RL environment
|
||||
# which will use it when calling `env.step()`.
|
||||
env = prl.envs.Env(world, state, reward)
|
||||
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
|
||||
Here are few examples that you can find in this folder that better demonstrate how to use the reward functions:
|
||||
|
||||
1. ``basics.py``: demonstrate the various features (operations) you can use with the ``Reward`` class.
|
||||
2. ``manipulator.py``: show how the distance cost decreases as you move the manipulator (with your mouse) closer to the target object in the world.
|
||||
3. ``forward_progress.py``: show how the reward function that measures how much a robot has moved forward increases / decreases based on the robot velocity. Use the arrow keys on your keyboard to move the robot, and observe how the computed reward value changes.
|
||||
|
||||
References:
|
||||
|
||||
.. [1] "Reinforcement Learning: An Introduction", Sutton and Barto, 1998
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python
|
||||
"""Demonstrate the various features (operations) you can use with the ``Reward`` class.
|
||||
|
||||
To illustrate the various operations we use the ``FixedReward``.
|
||||
|
||||
See the other examples to see how to use more complex reward functions.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
|
||||
# You can import in two ways reward functions
|
||||
import pyrobolearn as prl # import PRL
|
||||
from pyrobolearn.rewards import FixedReward # specify which function you want to import
|
||||
|
||||
# You can also import all the reward functions and the mathematical functions but I usually avoid it because
|
||||
# we do not know while reading the code where the various classes and other functionalities come from
|
||||
# from pyrobolearn.rewards import *
|
||||
|
||||
|
||||
# define two fixed reward functions
|
||||
r1 = prl.rewards.FixedReward(value=3)
|
||||
r2 = FixedReward(value=2, range=(-2, 2))
|
||||
|
||||
# print their value by calling them
|
||||
print("\nInitial rewards: r1 = {}, and r2 = {}".format(r1, r2))
|
||||
print("Initial reward value: r1() = {}, and r2() = {}".format(r1(), r2()))
|
||||
print("Initial reward range: range(r1) = {}, and range(r2) = {}".format(r1.range, r2.range))
|
||||
|
||||
# try to define a fixed reward function where the initial value is not in the defined range
|
||||
try:
|
||||
r3 = FixedReward(value=2, range=(-1, 1))
|
||||
except ValueError as e:
|
||||
print("\nTrying `r3=FixedReward(value=2, range=(-1,1))` results in an error: \n" + str(e) + "\n")
|
||||
|
||||
|
||||
# perform some mathematical operations on them
|
||||
r4 = 2 * prl.rewards.cos(r1) - 3 * r2
|
||||
|
||||
# print its value and range
|
||||
print("Perform mathematical operations on r1 and r2:")
|
||||
print("r4 = 2 * cos(r1) - 3 * r2 = {}".format(r4()))
|
||||
print("2 * cos(3) - 3 * 2 = {}".format(2 * np.cos(3) - 3 * 2))
|
||||
print("range(r4) = {}".format(r4.range))
|
||||
|
||||
|
||||
# try to perform an operation which it not authorized
|
||||
try:
|
||||
r5 = r1 / r2 # the range of r2 is [-2, 2] and thus there is a chance it could be 0 at one point
|
||||
except ValueError as e:
|
||||
print("\nTrying `r5 = r1 / r2` results in an error: \n" + str(e) + "\n")
|
||||
|
||||
|
||||
# The range of r2 is [-2, 2], if a reward function computes a reward value which is not in the range,
|
||||
# it will automatically be clipped.
|
||||
r2.value = 3 # you can only set the value for the FixedReward
|
||||
print("Setting r2.value=3 while its range is [-2, 2], and computing the reward will result in: r2={}".format(r2()))
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
"""Demonstrate how the reward function that measures how much a robot has moved forward increases / decreases based on
|
||||
the robot velocity. Use the arrow keys on your keyboard to move the robot, and observe how the computed reward value
|
||||
changes.
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# Create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create world
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# create wheeled robot
|
||||
robot = world.load_robot('epuck')
|
||||
|
||||
# create interface and bridge to control the robot with the keyboard
|
||||
interface = prl.tools.interfaces.MouseKeyboardInterface()
|
||||
bridge = prl.tools.bridges.BridgeMouseKeyboardDifferentialWheeledRobot(robot=robot, interface=interface)
|
||||
|
||||
# create state
|
||||
state = prl.states.BasePositionState(robot)
|
||||
|
||||
# create reward
|
||||
reward = 1000 * prl.rewards.ForwardProgressReward(state=state, direction=(1, 0, 0))
|
||||
|
||||
|
||||
# run simulation
|
||||
for t in count():
|
||||
# perform a step with the bridge and interface
|
||||
bridge.step(update_interface=True)
|
||||
|
||||
# update state: in this case it will get the base position state and will save it in the state instance
|
||||
state()
|
||||
|
||||
# compute reward: this will look in the previously given state instance its current state data
|
||||
print("Reward value = {}".format(reward()))
|
||||
|
||||
# perform a step in the simulator
|
||||
world.step(sim.dt)
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
"""Demonstrate how the distance cost decreases as you move the manipulator (with your mouse) closer to the target
|
||||
object in the world.
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# Create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create world
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# create robot
|
||||
robot = world.load_robot('kuka_iiwa')
|
||||
end_effector_id = robot.end_effectors[0]
|
||||
robot.print_info()
|
||||
|
||||
# desired position
|
||||
sphere = world.load_visual_sphere([0.5, 0., 0.], radius=0.05, color=(1, 0, 0, 0.5), return_body=True)
|
||||
|
||||
# create state
|
||||
state = prl.states.LinkWorldPositionState(robot, link_ids=end_effector_id)
|
||||
|
||||
# create reward
|
||||
# note that the given 'sphere' to the cost is not a state, and thus a PositionState will automatically be created
|
||||
# for that 'sphere', and called at each time the reward is computed.
|
||||
reward = prl.rewards.DistanceCost(state, sphere)
|
||||
|
||||
# run simulation
|
||||
for t in count():
|
||||
# update state
|
||||
state()
|
||||
|
||||
# compute reward
|
||||
print("Reward value = {}".format(reward()))
|
||||
|
||||
# perform a step in the simulator
|
||||
world.step(sim.dt)
|
||||
@@ -1,5 +1,22 @@
|
||||
## Robot examples
|
||||
|
||||
You can try to load different robot by typing `python <robot>.py`.
|
||||
More than 60 robots (of various types) are available through `pyrobolearn`.
|
||||
|
||||
To turn the camera in the simulator, keep pressing the `ctrl` key and the left button on the mouse, and move this last one.
|
||||
Here are the few examples that you can find in this folder:
|
||||
1. `load_robot.py <robot_name>`: load the given robot in the world.
|
||||
2. `visualize_robot.py <robot_name>`: test different visualization tools that can be used on the robot to show its
|
||||
joint axis, bounding boxes, and others.
|
||||
3. `robot_with_sliders.py <robot_name>`: load the given robot in the world and allow you to manipulate the robot's
|
||||
joints with sliders.
|
||||
4. `distribute_epucks.py`: distribute several e-pucks in the world and make them move forward.
|
||||
5. `quadcopter_controller.py`: move a quadcopter in the air using an Xbox or Playstation game controller.
|
||||
6. `robots/<robot>.py`: load the given robot in the simulator by directly instantiating it. Some of these files do
|
||||
more than just loading the robot.
|
||||
|
||||
Notes: to turn the camera in the simulator, keep pressing the `ctrl` key and the left button on the mouse, and
|
||||
move this last one.
|
||||
|
||||
|
||||
#### What to check next?
|
||||
|
||||
Check the `pyrobolearn/examples/interfaces` or `pyrobolearn/examples/kinematics` folder.
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python
|
||||
"""Distribute several e-pucks in the world and make them move forward.
|
||||
|
||||
You can move in the world using the keyboard and mouse:
|
||||
- `ctrl + left click`: rotate the camera
|
||||
- `scroll wheel` or `ctrl + right click`: zoom in/out
|
||||
- `ctrl + middle click`: move the camera
|
||||
- `left click` on an object: if the object has a mass and a collision shape, you can interact with it with the mouse
|
||||
- `w`: wireframe (see collision shapes)
|
||||
- `g`: show/hide menu
|
||||
- `esc`: quit the simulator
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from itertools import count
|
||||
import argparse
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create function for the parser to check the number of robots
|
||||
def check(number):
|
||||
"""check that the number of robots is between 1 and 100."""
|
||||
number = int(number)
|
||||
if number < 1:
|
||||
number = 1
|
||||
if number > 100:
|
||||
number = 100
|
||||
return number
|
||||
|
||||
|
||||
# create parser to select the robot
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-n', '--number', help='the number of epucks in the world', type=check, default=10)
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create basic world (with a floor and gravity enabled by default)
|
||||
world = prl.worlds.BasicWorld(sim, scaling=1)
|
||||
|
||||
# specify distribution ranges for position (x,y,z) and orientation (r,p,y)
|
||||
low_position, high_position = [-3, -3, 0], [3, 3, 0] # x,y,z
|
||||
low_orientation, high_orientation = [0, 0, -np.pi], [0, 0, np.pi] # r,p,y
|
||||
|
||||
# distribute the epucks in the world
|
||||
robots = world.distribute(world.load_robot, size=args.number, position_range=(low_position, high_position),
|
||||
rpy_range=(low_orientation, high_orientation), return_body=True, robot='epuck')
|
||||
|
||||
# run simulator
|
||||
for t in count():
|
||||
|
||||
# move each robot forward
|
||||
for robot in robots:
|
||||
robot.drive(speed=5)
|
||||
|
||||
# perform one step in the world
|
||||
world.step(sleep_dt=1. / 240)
|
||||
@@ -1,33 +1,44 @@
|
||||
# This file creates a basic world, load each robot that can be found in the PRL framework
|
||||
#!/usr/bin/env python
|
||||
"""Load a robot in a basic world.
|
||||
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import implemented_robots
|
||||
You can move in the world using the keyboard and mouse:
|
||||
- `ctrl + left click`: rotate the camera
|
||||
- `scroll wheel` or `ctrl + right click`: zoom in/out
|
||||
- `ctrl + middle click`: move the camera
|
||||
- `left click` on an object: if the object has a mass and a collision shape, you can interact with it with the mouse
|
||||
- `w`: wireframe (see collision shapes)
|
||||
- `g`: show/hide menu
|
||||
- `esc`: quit the simulator
|
||||
"""
|
||||
|
||||
robot_not_working = set(['icub'])
|
||||
from itertools import count
|
||||
import argparse
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# get implemented robots
|
||||
robots = prl.robots.implemented_robots
|
||||
print("All the robots (total number of robots = {}): {}".format(len(robots), robots))
|
||||
|
||||
# create parser to select the robot
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-r', '--robot', help='the robot to load in the world', type=str,
|
||||
choices=robots, default='hyq2max')
|
||||
args = parser.parse_args()
|
||||
|
||||
print("All the robots (total number of robots = {}): {}".format(len(implemented_robots), implemented_robots))
|
||||
|
||||
# create simulator
|
||||
sim = BulletSim()
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create basic world with floor and gravity
|
||||
world = BasicWorld(sim)
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# create one robot at a time
|
||||
for i, robot_name in enumerate(implemented_robots):
|
||||
if robot_name not in robot_not_working:
|
||||
# instantiate the given robot
|
||||
robot = world.load_robot(robot_name)
|
||||
# load the robot in the world (note that you can create the robot outside the world (not recommended),
|
||||
# and then give it to the `world.load_robot` method to let know the world that a robot was loaded)
|
||||
robot = world.load_robot(robot=args.robot, position=[0., 0.])
|
||||
|
||||
# print info about the robot
|
||||
print("Robot n{}: {}".format(i+1, robot))
|
||||
# robot.print_info()
|
||||
|
||||
# run for few moments in the world
|
||||
for t in range(250):
|
||||
# run one step and sleep a bit
|
||||
world.step(sleep_dt=1./240)
|
||||
|
||||
# remove the robot from the world
|
||||
world.remove(robot)
|
||||
# run simulator
|
||||
for _ in count():
|
||||
# perform one step in the world
|
||||
world.step(sleep_dt=1. / 240)
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python
|
||||
"""Control a quadcopter in the air using an Xbox or Playstation game controller.
|
||||
|
||||
how to run:
|
||||
```
|
||||
$ python quadcopter_controller.py --help # for help
|
||||
$ python quadcopter_controller.py --controller keyboard # to use the keyboard
|
||||
$ python quadcopter_controller.py --controller xbox # to use Xbox game controller
|
||||
$ python quadcopter_controller.py --controller ps # to use PS game controller
|
||||
```
|
||||
|
||||
Mapping of the keyboard interface:
|
||||
- `top arrow`: move forward
|
||||
- `bottom arrow`: move backward
|
||||
- `left arrow`: move sideways to the left
|
||||
- `right arrow`: move sideways to the right
|
||||
- `ctrl + top arrow`: ascend
|
||||
- `ctrl + bottom arrow`: descend
|
||||
- `ctrl + left arrow`: turn to the right
|
||||
- `ctrl + right arrow`: turn to the left
|
||||
- `space`: switch between first-person and third-person view
|
||||
|
||||
Mapping between the controller and the quadcopter:
|
||||
- left joystick: use to move the quadcopter
|
||||
- right joystick: use to ascend/descend and turn
|
||||
- south button (X on PlayStation and A on Xbox): change between the first-person and third-person view.
|
||||
- east button (circle on PlayStation and B on Xbox): increase the speed
|
||||
- west button (square on PlayStation and X on Xbox): decrease the speed
|
||||
"""
|
||||
|
||||
# import numpy as np
|
||||
from itertools import count
|
||||
import argparse
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create parser to select the game controller
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-c', '--controller', help='the controller to use', type=str,
|
||||
choices=['keyboard', 'xbox', 'ps'], default='keyboard')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# load corresponding interface
|
||||
if args.controller == 'keyboard': # keyboard interface
|
||||
from pyrobolearn.tools.interfaces.mouse_keyboard.mousekeyboard import MouseKeyboardInterface as Controller
|
||||
from pyrobolearn.tools.bridges.mouse_keyboard.bridge_mousekeyboard_quadcopter \
|
||||
import BridgeMouseKeyboardQuadcopter as Bridge
|
||||
elif args.controller == 'xbox': # Xbox interface
|
||||
from pyrobolearn.tools.interfaces.controllers.xbox import XboxControllerInterface as Controller
|
||||
from pyrobolearn.tools.bridges.controllers.robots.bridge_controller_quadcopter import BridgeControllerQuadcopter \
|
||||
as Bridge
|
||||
elif args.controller == 'ps': # PS interface
|
||||
from pyrobolearn.tools.interfaces.controllers.playstation import PSControllerInterface as Controller
|
||||
from pyrobolearn.tools.bridges.controllers.robots.bridge_controller_quadcopter import BridgeControllerQuadcopter \
|
||||
as Bridge
|
||||
else:
|
||||
raise NotImplementedError("Unknown game controller")
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create basic world (with a floor and gravity enabled by default)
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load quadcopter
|
||||
robot = prl.robots.Quadcopter(sim, position=[0., 0., 2.])
|
||||
world.load_robot(robot)
|
||||
|
||||
# load interface that accepts input events
|
||||
controller = Controller(use_thread=True, verbose=False)
|
||||
|
||||
# load bridge that connects the interface/controller with the quadcopter
|
||||
# The bridge is the one that maps the input events from the interface to commands sent to the quadcopter
|
||||
bridge = Bridge(quadcopter=robot, interface=controller)
|
||||
|
||||
# run simulator
|
||||
for t in count():
|
||||
# perform a step with the bridge and interface
|
||||
bridge.step(update_interface=True)
|
||||
|
||||
# perform one step in the world
|
||||
world.step(sleep_dt=1. / 240)
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
"""Manipulate the robot's joints with sliders.
|
||||
|
||||
You can move in the world using the keyboard and mouse:
|
||||
- `ctrl + left click`: rotate the camera
|
||||
- `scroll wheel` or `ctrl + right click`: zoom in/out
|
||||
- `ctrl + middle click`: move the camera
|
||||
- `left click` on an object: if the object has a mass and a collision shape, you can interact with it with the mouse
|
||||
- `w`: wireframe (see collision shapes)
|
||||
- `g`: show/hide menu
|
||||
- `esc`: quit the simulator
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
import argparse
|
||||
|
||||
import pyrobolearn as prl
|
||||
|
||||
|
||||
# create parser to select the robot
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-r', '--robot', help='the robot to load in the world', type=str,
|
||||
choices=prl.robots.implemented_robots, default='coman')
|
||||
parser.add_argument('-f', '--fixed_base', help='if we should fix the base when the robot has initially a floating '
|
||||
'base', type=bool, default=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
# create simulator
|
||||
sim = prl.simulators.Bullet()
|
||||
|
||||
# create basic world with floor and gravity
|
||||
world = prl.worlds.BasicWorld(sim)
|
||||
|
||||
# load the robot in the world
|
||||
robot = world.load_robot(robot=args.robot, position=[0., 0.], fixed_base=args.fixed_base)
|
||||
|
||||
# add a slider for each specified joint
|
||||
robot.add_joint_slider(joint_ids=robot.joints)
|
||||
|
||||
# run simulator
|
||||
for _ in count():
|
||||
# update the joint slider
|
||||
robot.update_joint_slider()
|
||||
|
||||
# perform one step in the world
|
||||
world.step(sleep_dt=1. / 240)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Aibo
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import AllegroHand
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Ant
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Atlas
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Ballbot
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Baxter
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import BB8
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -85,12 +85,12 @@ class LQR(object):
|
||||
if __name__ == "__main__":
|
||||
import numpy as np
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import World
|
||||
from pyrobolearn.robots import CartPole
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = World(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Cassie
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Centauro
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Cogimon
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||
@@ -3,12 +3,12 @@
|
||||
"""
|
||||
|
||||
from itertools import count
|
||||
from pyrobolearn.simulators import BulletSim
|
||||
from pyrobolearn.simulators import Bullet
|
||||
from pyrobolearn.worlds import BasicWorld
|
||||
from pyrobolearn.robots import Coman
|
||||
|
||||
# Create simulator
|
||||
sim = BulletSim()
|
||||
sim = Bullet()
|
||||
|
||||
# create world
|
||||
world = BasicWorld(sim)
|
||||