Skip to content

Commit

Permalink
Merge pull request #61 from haosulab/sphinx
Browse files Browse the repository at this point in the history
Sphinx
  • Loading branch information
KolinGuo authored Feb 5, 2024
2 parents a1076fd + 95174e2 commit c5b93ae
Show file tree
Hide file tree
Showing 48 changed files with 657 additions and 9,979 deletions.
17 changes: 17 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: "2"

build:
os: "ubuntu-22.04"
tools:
python: "3.10"

python:
install:
- requirements: docs/requirements.txt

sphinx:
configuration: docs/source/conf.py

formats:
- pdf
- epub
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# MPlib

<p align="center">
<img src="demo.gif">
<img src="https://raw.githubusercontent.com/haosulab/MPlib/main/docs/demo.gif">
</p>

[![PyPI - Version](https://img.shields.io/pypi/v/mplib)](https://pypi.org/project/mplib/)
Expand Down
23 changes: 0 additions & 23 deletions dev/generate_stub_and_doc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,26 +70,3 @@ echo_info "Moving generated stubs into 'mplib/pymp'"
mv -v stubs/mplib/pymp/* mplib/pymp
echo_info "Removing 'stubs/'"
rm -rfv stubs/

############################################################
# Section 3: Build docs #
############################################################
# TODO: switch to other tools to generate docs, README.md should not be included in wheels
# TODO: do we must install sapien to generate doc?
BUILD_DOC_CMD="\
export PATH=\"\$(find /opt/python -name \"cp${PY_VERSION}*\")/bin:\${PATH}\" \
&& python3 -m pip install pdoc \
&& python3 -m pip install sapien==3.0.0.dev0 \
&& python3 -m pip install wheelhouse/mplib*.whl \
&& cp -v README.md /opt/python/cp${PY_VERSION}-cp${PY_VERSION}/lib/python*/site-packages/mplib \
&& pdoc -o docs mplib
"

echo_info "Removing previous docs under 'mplib/docs/'"
rm -rfv mplib/docs/

echo_info "Building docs in docker '${IMGNAME}'"
docker run -it --rm \
-v "$REPO_DIR":/${REPO_NAME} \
"$IMGNAME" \
bash -c "$BUILD_DOC_CMD"
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
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)
File renamed without changes
7 changes: 0 additions & 7 deletions docs/index.html

This file was deleted.

35 changes: 35 additions & 0 deletions docs/make.bat
Original file line number Diff line number Diff line change
@@ -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

%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.https://www.sphinx-doc.org/
exit /b 1
)

if "%1" == "" goto help

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd
283 changes: 0 additions & 283 deletions docs/mplib.html

This file was deleted.

243 changes: 0 additions & 243 deletions docs/mplib/examples.html

This file was deleted.

697 changes: 0 additions & 697 deletions docs/mplib/examples/collision_avoidance.html

This file was deleted.

797 changes: 0 additions & 797 deletions docs/mplib/examples/constrained_planning.html

This file was deleted.

608 changes: 0 additions & 608 deletions docs/mplib/examples/demo.html

This file was deleted.

1,115 changes: 0 additions & 1,115 deletions docs/mplib/examples/demo_setup.html

This file was deleted.

631 changes: 0 additions & 631 deletions docs/mplib/examples/detect_collision.html

This file was deleted.

669 changes: 0 additions & 669 deletions docs/mplib/examples/moving_robot.html

This file was deleted.

1,007 changes: 0 additions & 1,007 deletions docs/mplib/examples/two_stage_motion.html

This file was deleted.

3,551 changes: 0 additions & 3,551 deletions docs/mplib/planner.html

This file was deleted.

238 changes: 0 additions & 238 deletions docs/mplib/pymp.html

This file was deleted.

3 changes: 3 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
myst-parser
sphinx-rtd-theme
mplib
46 changes: 0 additions & 46 deletions docs/search.js

This file was deleted.

35 changes: 35 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = "mplib"
author = "Minghua Liu, Jiayuan Gu, Kolin Guo, Xinsong Lin"
copyright = f"2021-2024, {author}. All rights reserved."
release = "0.1.0"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.duration",
"sphinx.ext.napoleon",
"sphinx.ext.viewcode",
"sphinx_rtd_theme",
"myst_parser",
]

templates_path = ["_templates"]
exclude_patterns = []


# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = "sphinx_rtd_theme"
html_static_path = ["_static"]
41 changes: 41 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.. mplib documentation master file, created by
sphinx-quickstart on Fri Jan 19 09:35:13 2024.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to mplib's documentation!
=================================

.. include:: ../../README.md
:parser: myst_parser.sphinx_

Planner Documentation
---------------------

.. toctree::
:maxdepth: 1

mplib

Examples
-----------

.. toctree::
:maxdepth: 1

../tutorials/examples

API Reference
-------------

.. toctree::
:maxdepth: 1

mplib.pymp

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
42 changes: 42 additions & 0 deletions docs/source/mplib.pymp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
API Doc
========

articulation
------------------------------------------

.. automodule:: mplib.pymp.articulation
:members:
:undoc-members:
:show-inheritance:

fcl
-------------------------------------------

.. automodule:: mplib.pymp.fcl
:members:
:undoc-members:
:show-inheritance:

ompl
--------------------------

.. automodule:: mplib.pymp.ompl
:members:
:undoc-members:
:show-inheritance:

pinocchio
---------------------------------

.. automodule:: mplib.pymp.pinocchio
:members:
:undoc-members:
:show-inheritance:

planning\_world
---------------------------------------

.. automodule:: mplib.pymp.planning_world
:members:
:undoc-members:
:show-inheritance:
10 changes: 10 additions & 0 deletions docs/source/mplib.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Planner
=======

mplib.planner
--------------------

.. automodule:: mplib.planner
:members:
:undoc-members:
:show-inheritance:
Binary file added docs/source/tutorials/assets/RRT.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/tutorials/assets/collision1.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/tutorials/assets/collision2.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/tutorials/assets/collision3.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/tutorials/assets/screw.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/tutorials/assets/two_stage_motion.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions docs/source/tutorials/collision_avoidance.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
.. _collision_avoidance:

Collision Avoidance
====================


In :ref:`plan_a_path`, we talked about how to plan paths for the robot. However, in that tutorial, we didn't take the environment model into account. The robot will avoid self-collisions (i.e., collisions between the robot links), but may collide with the environment.

This tutorial will introduce two ways two ways to avoid collisions: add environment point clouds and attach a box. As shown in the right figure, the robot needs to move the red box to the place of the green box while avoiding collision with the blue box. The full script can be found here :download:`demo.py <../../../mplib/examples/collision_avoidance.py>`. You will also need :download:`demo_setup.py <../../../mplib/examples/demo_setup.py>` and grab the panda URDF..

.. image:: assets/collision1.gif
:width: 32%
.. image:: assets/collision2.gif
:width: 32%
.. image:: assets/collision3.gif
:width: 32%

The above figures show the benefit of collision avoidance:

- Left: w/o point cloud, w/o attach. The robot arm hits the blue box.
- Middle: w/ point cloud, w/o attach. The red box hits the blue box.
- Right: w/ point cloud, w/ attach. There is no collision.

Add environment point clouds
--------------------------------------

One way to model the environment and avoid collision is through point clouds. The point cloud may come from the sensor observations or be sampled from the mesh surfaces. For example, we can add a point cloud for the blue box with ``planner.update_point_cloud()``:

.. literalinclude:: ../../../mplib/examples/collision_avoidance.py
:dedent: 0
:start-after: # add_point_cloud ankor
:end-before: # add_point_cloud ankor end
:emphasize-lines: 4

``planner.update_point_cloud()`` takes two arguments. The first one is a NumPy array of shape :math:`(n \times 3)`, which describes the coordinates of the points. **The coordinates should be represented in the world frame**. The second (optional) argument is ``radius``, which describes the radius of each point. This can be used to create a buffer around the collision object.

After adding the point cloud, we can avoid collisions between the robot and the point cloud by setting ``use_point_cloud`` to be True. Both ``planner.plan_qpos_to_pose()`` and ``planner.plan_screw()`` support this flag:

.. literalinclude:: ../../../mplib/examples/demo_setup.py
:dedent: 0
:start-after: # plan_qpos_to_pose ankor
:end-before: # plan_qpos_to_pose ankor end
:emphasize-lines: 5

You don't need to provide the point cloud for each ``planner.plan()`` or ``planner.plan_screw()`` call. You can use ``planner.update_point_cloud()`` to update the point cloud once it's changed.

.. note::
Please remember to remove the points of the robot arm if the points come from the sensor observation. Otherwise, there will always be collisions, and the planner may fail to plan a valid path.

Attach a box
--------------------------------------
As shown in the above figure (middle one), after adding the point cloud of the blue box, the robot will not collide with it. However, the red box moves with the robot, and it may still collide with the blue box. To address this issue, we can attach a box to the robot, so that we can avoid the collision between the attached box and the environment point cloud:

.. literalinclude:: ../../../mplib/examples/collision_avoidance.py
:dedent: 0
:start-after: # use_attach ankor
:end-before: # use_attach ankor end

``planner.update_attached_box()`` takes three arguments:

- ``size``: a list with three elements indicates the size of the attached box.
- ``pose``: a list with seven elements indicates the relative pose from the box to the attached link. The first three elements describe the position part, and the remaining four elements describe the quaternion (wxyz) for the rotation part.
- ``link_id = -1``: optional, an integer indicates the id of the link that the box is attached to. The link id is determined by the ``user_link_names`` (during Configuration), and starts from 0. The default value -1 indicates the ``move_group`` link.

After adding the attached box, we can avoid collisions between the attached box and the point cloud by setting both ``use_point_cloud`` and ``use_attach`` to be True. Both ``planner.plan_qpos_to_pose()`` and ``planner.plan_screw()`` support the flags.

You can use ``planner.update_attached_box()`` again to update the box once it's changed.

As shown in the above figure (the right one), after adding the point cloud of the blue box and attaching the red box to the ``move_group`` link, there is no collision.

.. note::
There are also a family of update attach functions. One can attach a sphere or a general mesh. Please see the planner API for more details.
39 changes: 39 additions & 0 deletions docs/source/tutorials/constrained_planning.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.. constrained_planning
Constrained Planning
====================

.. image:: assets/constrained_planning.gif
:width: 50%

This is a simple implementation of a constrained planner. It is based on OMPL's projection-based planner. Roughly, OMPL does sampling based planning and projects a joint configuration into a valid configuration using the constrained function we provide. The above gif shows the robot execute two trajectories. The first one generated with constraint that the z-axis of the endeffector pointing downwards. The second one generated without any constraints. We can see that the second trajectory tilts the endeffector sideways.

Defining the Constrained Function
---------------------------------

The constrained function is a :math:`R^d \rightarrow R` function that evaulates to zero when the configuration is valid and non-zero otherwise. In this example, we define a constrained function that evaluates to zero when the z-axis of the endeffector is pointing downwards.

.. literalinclude:: ../../../mplib/examples/constrained_planning.py
:language: python
:start-after: # constraint function ankor
:end-before: # constraint function ankor end

Moreover, due to the projection-based method, we also need to provide the jacobian of the constrained function. In this example, we define the jacobian of the constrained function as follows.

.. literalinclude:: ../../../mplib/examples/constrained_planning.py
:language: python
:start-after: # constraint jacobian ankor
:end-before: # constraint jacobian ankor end

One can usually calculate the jacobian of the constraint by manipulating the jacobian of the forward kinematics. We need the jacobian calculation to be fast or else the planner will be slow. In the case above, we used the single link jacobian of the endeffector and used its rotational part to calculate how much the z-axis of the endeffector is changing.

Using the Constrained Planner
-----------------------------

The interface to the constrained planner is just some parameters when calling the planning function. We need to pass in the constrained function as well as its jacobian. Optinally, pass in the tolerance for the projection.

.. literalinclude:: ../../../mplib/examples/constrained_planning.py
:language: python
:start-after: # with constraint
:end-before: # without constraint
:emphasize-lines: 12-14
Loading

0 comments on commit c5b93ae

Please sign in to comment.