Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Humanoid Path Planner Documentation

A motion planning toolkit for kinematic chains evolving among obstacles — from industrial robot arms to full humanoids.

Introduction

HPP is a C++ Software Developement Kit implementing path planning for kinematic chains in environments cluttered with obstacles. Collision checking is performed by a modified version of the Flexible Collision Library developed at University of North Carolina. Robots can be loaded from URDF model. It is a collection of software packages handled by cmake and pkg-config.

Why HPP?

HPP is not a toy planner: it is built to handle the kind of complex, contact-rich motion planning problems found in real robotics applications.

  • Built for complex kinematic chains — from single manipulator arms to full humanoids and multi-robot systems.
  • Manipulation planning out of the boxhpp-manipulation handles grasping, regrasping, and multi-contact scenarios, not just collision-free transit paths.
  • Fast, reliable collision checking — powered by a modified Flexible Collision Library (coal) under hpp-pinocchio.
  • Python-first workflow — define scenes, robots, and planning problems from simple Python scripts via hpp-python, with the heavy algorithmic lifting handled in C++.
  • Flexible visualization — watch your robot plan and move in a web browser with viser, or plug into your existing ROS/ROS2 setup with rviz2 or gazebo.
  • Battle-tested on real industrial use cases — surface treatment, welding, and assembly tasks, as shown below.

Applications

HPP is already used to plan motions for real industrial robotic tasks — here are a few examples in action.

Surface treatment

Planning a tool path to sweep and abrade the surface of a cylinder, while avoiding self-collisions and obstacles in the workspace.

Welding

Planning collision-free trajectories for a welding tool around complex parts.

Assembly / construction

Planning manipulation sequences to assemble a structure piece by piece, combining grasping, regrasping, and placement.

Overview of the architecture

flowchart TB
    HPPY["hpp-python"]
    subgraph HPP_STACK["HPP stack"]
        direction TB
        HM["hpp-manipulation"]
        HC["hpp-core"]
        HCONS["hpp-constraints"]
        HPIN["hpp-pinocchio"]
        HM --> HC
        HC --> HCONS
        HCONS --> HPIN
    end
    PIN["pinocchio"]
    COAL["coal"]
    HPIN --> PIN
    HPIN --> COAL
    HPPY --> HPP_STACK
   subgraph HPP_VIZ["HPP Visualization"]
        direction TB
        VW["Viewer"]
        GPV["Gepetto Viewer"]
        GV["Graph Viewer"]
        VW --> GPV
        VW --> GV
   end
   HPPY -->  |import| VW
classDef external fill:#C8E6C9,stroke:#2E7D32;
class PIN,COAL external

The software is composed of C++ libraries implementing the algorithms. Python bindings built on Boost.Python are provided to help users easily define and solve problems. Visualization of the scene can be done in a web browser using viser, or using ROS/ROS2 with rviz2 or gazebo.

The algorithmic part, built on hpp-manipulation is embedded in several Python modules by hpp-python. From a Python script, users can define scenes containing robots and environments, they can also define and solve motion planning problems. Results of path planning requests as well as individual configurations can be displayed in a web browser via package hpp-gepetto-viewer.

Getting started

Package hpp_tutorial provides some examples of how to use this project. Lets start now ! Tutorial

Acknowledgement

Logo projet ROMEO Logo EUROC project Framework Program 7 Logo ERC EU Project: Factory-in-a-day Logo ANR project Logo ROB4FAM RoboCom++

Contributors

Thanks to all the contributors of the HPP project:

How to Contribute

Thanks for your interest in contributing to this project! Here are a few simple guidelines to follow.

Reporting a bug

  • Check that a similar issue doesn’t already exist in the Issues section.
  • Open a new issue describing:
    • the expected behavior and the observed behavior,
    • steps to reproduce the problem,
    • your environment (OS, package version, compiler, Python version…).

Proposing a change (Pull Request)

  1. Fork the repository, then clone your fork.
  2. Create a dedicated branch from devel:
    git checkout -b my-feature
    
  3. Make your changes, keeping commits clear and atomic.
  4. Follow the existing code style of the file you’re modifying (C++ or Python).
  5. If you add a feature, add or update the corresponding tests.
  6. Make sure the project builds and the tests pass:
    cmake -B build
    cmake --build build
    cmake --build build -t test
    
  7. Push your branch and open a Pull Request against the upstream repository.
  8. Clearly describe what your PR does and why.

Pre-commit

This project uses prek (a faster, drop-in replacement for pre-commit) to automatically check code formatting and quality before each commit.

  1. Install prek (one-time setup): follow the instructions at https://prek.j178.dev/installation/
  2. Enable the hooks in your local clone:
prek install
  1. From then on, checks run automatically on every git commit. You can also run them manually on all files:
prek run --all-files
  1. If a hook modifies files (auto-formatting), stage those changes and commit again:
git add -u
git commit

The repository also uses pre-commit.ci, so the hooks will automatically be checked on your Pull Request as well.

Commit messages

  • Use short, descriptive, imperative-mood messages (e.g. Fix collision check in hpp-core).
  • One change = one commit whenever possible.

License

By contributing, you agree that your code will be distributed under the project’s license (see the LICENSE file of the relevant repository).

Questions

For any questions, open an issue or check the documentation at https://humanoid-path-planner.github.io/hpp-doc/

Installation

Choosing the Right Installation Method

MethodStableRequires CompilationUses NixRecommended For
Stable - BinaryNoMost users
Stable - SourceYesAdvanced users
Stable - Nix Environment (HPP Binary Packages)NoNix users
Development - SourceYesContributors and testers
Development - Nix Environment (HPP Sources)YesHPP developers
ROS - SourceYesROS users

Binary installation on Ubuntu 24.04 64 bit

To install HPP packages on Ubuntu 24.04 LTS 64 bit, follow these steps.

1. Install basic tools

sudo apt-get install git cmake curl doxygen lsb-release make wget

2. Install robotpkg

Install robotpkg by following the robotpkg installation website.

3. Install HPP

pyver=312
sudo apt-get install robotpkg-py${pyver}-hpp-manipulation-corba \
robotpkg-py${pyver}-qt5-hpp-gepetto-viewer

4. Install optional extra packages for demonstrations

Tutorials

sudo apt-get install robotpkg-py${pyver}-hpp-tutorial \
robotpkg-py${pyver}-qt5-hpp-practicals

GUI

sudo apt-get install robotpkg-py${pyver}-qt5-hpp-gui \
robotpkg-py${pyver}-qt5-hpp-plot

Robot descriptions

sudo apt-get install robotpkg-py${pyver}-hpp-environments \
robotpkg-romeo-description

5. Choose a directory for the documentation

Define the environment variable DEVEL_HPP_DIR with the full path to this directory.

  • The documentation will be cloned into DEVEL_HPP_DIR/install.

It is recommended to set DEVEL_HPP_DIR in your .bashrc for future use.

mkdir -p $DEVEL_HPP_DIR/src

6. Copy configuration files

wget -O $DEVEL_HPP_DIR/config.sh https://raw.githubusercontent.com/humanoid-path-planner/hpp-doc/stable/doc/config/ubuntu-24.04.sh

wget -O $DEVEL_HPP_DIR/src/Makefile https://raw.githubusercontent.com/humanoid-path-planner/hpp-doc/stable/makefiles/devel.mk

7. Configure the environment

Go to {DEVEL_HPP_DIR} source config.sh


## 8. Build the documentation

Go to the source directory and install the documentation:

```bash
cd ${DEVEL_HPP_DIR}/src
make hpp-doc.install hpp-practicals.checkout hpp_tutorial.checkout

9. Documentation access

Open:

$DEVEL_HPP_DIR/install/share/doc/hpp-doc/index.html

in a web browser to access the documentation of most HPP packages.

Binary installation on Ubuntu 22.04 64 bit

To install HPP packages on Ubuntu 22.04 LTS 64 bit, follow these steps.

1. Install robotpkg

Install robotpkg by following the robotpkg installation website.

2. Install HPP

pyver=310
sudo apt-get install robotpkg-py<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">h</span><span class="mord mathnormal">pp</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">mani</span><span class="mord mathnormal">p</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">cor</span><span class="mord mathnormal">ba</span><span class="mspace"> </span><span class="mord mathnormal">ro</span><span class="mord mathnormal">b</span><span class="mord mathnormal">o</span><span class="mord mathnormal">tp</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span>{pyver}-qt5-hpp-gepetto-viewer

3. Install optional extra packages for demonstrations

Tutorials

sudo apt-get install robotpkg-py${pyver}-hpp-tutorial

GUI

sudo apt-get install robotpkg-py${pyver}-qt5-hpp-gui \
robotpkg-py${pyver}-qt5-hpp-plot

Robot descriptions

sudo apt-get install robotpkg-py${pyver}-hpp-environments \
robotpkg-romeo-description

Documentation

sudo apt-get install robotpkg-hpp-doc

4. Setup environment variables

Add the following lines to your .bashrc file (adjust the Python version if necessary):

export PATH=/opt/openrobots/bin<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{PATH}
export LD_LIBRARY_PATH=/opt/openrobots/lib<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal">L</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">L</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.00773em;">BR</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{LD_LIBRARY_PATH}
export PYTHONPATH=/opt/openrobots/lib/python3.10/site-packages<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal" style="margin-right:0.13889em;">ONP</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{PYTHONPATH}
export ROS_PACKAGE_PATH=/opt/openrobots/share<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.02778em;">RO</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mord mathnormal">A</span><span class="mord mathnormal">G</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{ROS_PACKAGE_PATH}

export CMAKE_PREFIX_PATH=/opt/openrobots<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.10903em;">CM</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.13889em;">REF</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{CMAKE_PREFIX_PATH}
export PKG_CONFIG_PATH=/opt/openrobots<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.13889em;">ONF</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{PKG_CONFIG_PATH}

5. Documentation access

Open:

/opt/openrobots/share/doc/hpp-doc/index.html

in a web browser to access the documentation of most HPP packages.

Binary installation on Ubuntu 20.04 64 bit with ROS Noetic

To install HPP packages on Ubuntu 20.04 LTS 64 bit with ROS Noetic, follow these steps.

1. Install ROS Noetic

Install ROS Noetic by following steps 1.1 to 1.3 of the ROS installation website.

2. Install robotpkg

Install robotpkg by following the robotpkg installation website.

3. Install HPP

pyver=38
sudo apt-get install robotpkg-py<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">h</span><span class="mord mathnormal">pp</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">mani</span><span class="mord mathnormal">p</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">cor</span><span class="mord mathnormal">ba</span><span class="mspace"> </span><span class="mord mathnormal">ro</span><span class="mord mathnormal">b</span><span class="mord mathnormal">o</span><span class="mord mathnormal">tp</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span>{pyver}-qt5-hpp-gepetto-viewer

4. Install optional extra packages for demonstrations

Tutorials

sudo apt-get install robotpkg-py${pyver}-hpp-tutorial

GUI

sudo apt-get install robotpkg-py${pyver}-qt5-hpp-gui \
robotpkg-py${pyver}-qt5-hpp-plot

Robot descriptions

sudo apt-get install ros-noetic-pr2-description \
robotpkg-py${pyver}-hpp-environments \
robotpkg-romeo-description

Documentation

sudo apt-get install robotpkg-hpp-doc

5. Setup environment variables

Add the following lines to your .bashrc file:

source /opt/ros/noetic/setup.bash

export PATH=/opt/openrobots/bin<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{PATH}
export LD_LIBRARY_PATH=/opt/openrobots/lib<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal">L</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">L</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.00773em;">BR</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{LD_LIBRARY_PATH}
export PYTHONPATH=/opt/openrobots/lib/python2.7/site-packages<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal" style="margin-right:0.13889em;">ONP</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{PYTHONPATH}
export ROS_PACKAGE_PATH=/opt/openrobots/share<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.02778em;">RO</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mord mathnormal">A</span><span class="mord mathnormal">G</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{ROS_PACKAGE_PATH}

export CMAKE_PREFIX_PATH=/opt/openrobots<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.10903em;">CM</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.13889em;">REF</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{CMAKE_PREFIX_PATH}
export PKG_CONFIG_PATH=/opt/openrobots<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.13889em;">ONF</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span></span>{PKG_CONFIG_PATH}

6. Documentation access

Open:

/opt/openrobots/share/doc/hpp-doc/index.html

in a web browser to access the documentation of most HPP packages.

Source installation on Ubuntu 24.04 64 bit

To install HPP and its dependencies from source on Ubuntu 24.04 LTS 64 bit, follow these steps.

1. Install robotpkg

Install robotpkg by following the robotpkg installation website.

2. Install dependencies using apt-get

sudo apt-get update && sudo apt-get install \
assimp-utils cmake coinor-libipopt-dev coinor-libipopt1v5 cython3 doxygen \
git ffmpeg gcovr gfortran graphviz libassimp-dev libboost-all-dev \
libbullet-dev libccd-dev libcdd-dev libconsole-bridge-dev libeigen3-dev \
libglpk-dev libgraphviz-dev libgtest-dev liblapack-dev liblog4cxx-dev \
libltdl-dev liboctomap-dev libopencv-dev libpcl-dev libqt5svg5-dev \
libqt5xmlpatterns5-dev libtinyxml2-dev libtinyxml-dev libtool-bin \
liburdfdom-dev liburdfdom-headers-dev libyaml-cpp-dev llvm m4 \
oxygen-icon-theme pkg-config psmisc pyqt5-dev python3-defusedxml \
python3-dev python3-empy python3-gnupg python3-matplotlib python3-venv \
python3-netifaces python3-nose python3-numpy python3-paramiko \
python3-pydot python3-pyqt5 python3-scipy python3-setuptools \
python3-sip-dev python3-sphinx python3-yaml python3-pip python-is-python3 \
qtbase5-private-dev qtmultimedia5-dev texlive-latex-extra wget \
robotpkg-romeo-description robotpkg-py312-eigenpy robotpkg-py312-coal \
robotpkg-py312-pinocchio robotpkg-py312-proxsuite robotpkg-qt5-qgv

3. Choose a development directory

Choose a directory on your filesystem and define the environment variable DEVEL_HPP_DIR with its full path.

  • The packages will be cloned into DEVEL_HPP_DIR/install.

It is recommended to set DEVEL_HPP_DIR in your .bashrc file for future use.

mkdir -p $DEVEL_HPP_DIR/src

4. Copy configuration files

wget -O $DEVEL_HPP_DIR/config.sh https://raw.githubusercontent.com/humanoid-path-planner/hpp-doc/stable/doc/config/ubuntu-24.04.sh

wget -O $DEVEL_HPP_DIR/src/Makefile https://raw.githubusercontent.com/humanoid-path-planner/hpp-doc/stable/makefiles/stable.mk

5. Configure the environment

Go to DEVEL_HPP_DIR source config.sh


## 6. Install Python dependencies

Create a Python virtual environment and install the required Python packages:

```bash
python -m venv <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.13889em;">NST</span><span class="mord mathnormal">A</span><span class="mord mathnormal">L</span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">D</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span>INSTALL_PIP_DIR/bin/pip install "numpy==1.26.4" trimesh pycollada viser

7. Build and install the packages

Go to the source directory and build the packages:

cd ${DEVEL_HPP_DIR}/src
make all

8. Documentation access

Open:

$DEVEL_HPP_DIR/install/share/doc/hpp-doc/index.html

in a web browser to access the documentation of most HPP packages.

Binary setup with Nix

To open a Nix development environment with all HPP packages already compiled, follow these steps.

Install and configure direnv with nix-direnv.

This step is already done on LAAS computers.

Configure the Gepetto Nix binary cache:

Gepetto binary cache

This step is already done on LAAS computers.

3. Activate the HPP binary Nix environment

In the current working directory, create the environment configuration:

echo "use flake github:gepetto/nix#hpp-bin" > .envrc
direnv allow

If you do not want to use nix-direnv, you can alternatively run:

nix develop github:gepetto/nix#hpp-bin

However, this command must be executed manually in each new shell.

Source installation on ubuntu-24.04 64 bit

To install all the packages on ubuntu 24.04 LTS 64 bit, you should do the following steps:

1. Install dependencies

install robotpkg: follow the robotpkg installation website.

2. Install by apt-get

  sudo apt-get update && apt-get install \
  assimp-utils cmake coinor-libipopt-dev coinor-libipopt1v5 cython3 doxygen \
  git ffmpeg gcovr gfortran graphviz libassimp-dev libboost-all-dev \
  libbullet-dev libccd-dev libcdd-dev libconsole-bridge-dev libeigen3-dev \
  libglpk-dev libgraphviz-dev libgtest-dev liblapack-dev liblog4cxx-dev \
  libltdl-dev liboctomap-dev libopencv-dev libpcl-dev libqt5svg5-dev \
  libqt5xmlpatterns5-dev libtinyxml2-dev libtinyxml-dev libtool-bin \
  liburdfdom-dev liburdfdom-headers-dev libyaml-cpp-dev llvm m4 \
  oxygen-icon-theme pkg-config psmisc pyqt5-dev python3-defusedxml \
  python3-dev python3-empy python3-gnupg python3-matplotlib python3-venv\
  python3-netifaces python3-nose python3-numpy python3-paramiko \
  python3-pydot python3-pyqt5 python3-scipy python3-setuptools \
  python3-sip-dev python3-sphinx python3-yaml python3-pip python-is-python3 \
  qtbase5-private-dev qtmultimedia5-dev texlive-latex-extra wget \
  robotpkg-romeo-description robotpkg-py312-eigenpy robotpkg-py312-coal \
  robotpkg-py312-pinocchio robotpkg-py312-proxsuite robotpkg-qt5-qgv

3. Choose a directory on your file system

  • Define the environment variable DEVEL_HPP_DIR with the full path to this directory.
  • the packages will be cloned into DEVEL_HPP_DIR/install.

It is recommanded to set variable DEVEL_HPP_DIR in your .bashrc for future use.

mkdir -p $DEVEL_HPP_DIR/src

4. Copy Config and Makefile

  wget -O $DEVEL_HPP_DIR/config.sh https://raw.githubusercontent.com/humanoid-path-planner/hpp-doc/stable/doc/config/ubuntu-24.04.sh
  wget -O $DEVEL_HPP_DIR/src/Makefile https://raw.githubusercontent.com/humanoid-path-planner/hpp-doc/stable/makefiles/devel.mk

5. cd into $DEVEL_HPP_DIR and type

  cd $DEVEL_HPP_DIR
  source config.sh

6. install some dependencies via pip

  python -m venv $INSTALL_PIP_DIR
  $INSTALL_PIP_DIR/bin/pip install "numpy==1.26.4" trimesh pycollada viser

7. cd into $DEVEL_HPP_DIR/src and type

  cd ${DEVEL_HPP_DIR}/src
  make all

8. Documentation acces

open $DEVEL_HPP_DIR/install/share/doc/hpp-doc/index.html in a web brower and you will have access to the documentation of most packages.

Source installation with Nix

To compile all HPP packages inside a Nix development environment, follow these steps.

Install and configure direnv with nix-direnv.

This step is already done on LAAS computers.

Configure the Gepetto Nix binary cache:

Gepetto binary cache

This step is already done on LAAS computers.

3. Choose a development directory

Choose a directory on your filesystem. This directory will be referred to as DEVEL_HPP_DIR.

  • The packages will be cloned into DEVEL_HPP_DIR/install.

Create the directory and enter it:

mkdir -p $DEVEL_HPP_DIR
cd $DEVEL_HPP_DIR

4. Activate the HPP Nix environment

Create the .envrc file:

echo "use flake github:gepetto/nix#hpp" > .envrc
direnv allow

If you do not want to use nix-direnv, you can alternatively run:

nix develop github:gepetto/nix#hpp

However, this command must be executed manually in each new shell.

The Nix environment will define the DEVEL_HPP_DIR environment variable to the current working directory.

5. Get the Makefile

Download the Makefile:

wget -O $DEVEL_HPP_DIR/src/Makefile https://raw.githubusercontent.com/humanoid-path-planner/hpp-doc/devel/makefiles/devel.mk

6. Compile all packages

Build all HPP packages:

cd $DEVEL_HPP_DIR/src
make all

ROS — Source

Source installation with ROS

To compile all the packages in a ROS workspace, you can follow these steps:

  1. Choose, setup, and activate a ROS distribution: https://www.ros.org/blog/getting-started/

  2. Choose a directory on your file system which we will call DEVEL_HPP_DIR.

    • the packages will be cloned into $DEVEL_HPP_DIR/src,
    • the packages will be installed in $DEVEL_HPP_DIR/install.

    Create that directory and enter inside

  3. Download our repos file to clone HPP packages with vcs2l:

```bash
mkdir -p $DEVEL_HPP_DIR/src
wget -O $DEVEL_HPP_DIR/hpp.repos https://raw.githubusercontent.com/humanoid-path-planner/hpp-doc/devel/ros/devel.repos
vcs import --input hpp.repos src
```
  1. Compile all packages with colcon:
```bash
colcon build
```
  1. Activate the install prefix of the workspace
```bash
source install/setup.bash
```

Tutorial for humanoid path planner platform.

This package provides some tutorials to learn how to use Humanoid Path Planner software. The various tutorials are:

  1. tutorial 1 How to install and run the software.
  2. tutorial 2 How to define and solve a simple pick and place problem.
  3. tutorial 3 How to use HPP in manufacturing.
  4. tutorial 4 How to control the trajectory of a tool.
  5. tutorial 5 How to optimize and time-parameterize paths.
  6. tutorial 6 How to use the rviz2 vizualization.
  7. tutorial 7 How to execute motions on a simulated robot.
  8. tutorial 8 Pick and place with gripper, introducing pre and post-actions.
  9. tutorial 9 A more efficient way to assign pre or post-actions.

Pipeline status Coverage report Code style: black pre-commit.ci status

Installing the software

This tutorial provides a quick procedure to install the software in docker. For general installation instructions, please visit the project page

Prerequisite

You need a machine running linux with docker installed. See https://docs.docker.com/engine/install/ubuntu for docker installation instructions.

Installing HPP in a docker image

We will build a minimal docker image containing HPP software from binary packages. Then we will run the image in a container that shares a directory with the host machine. Docker will create a user in the container. In order to avoid file ownership conflicts between this user and your account on your machine, we will make them use the same user id and group.

  1. Create an empty directory on your machine that will be shared by the container and cd into this directory.
  2. Download the Dockerfile to build the docker image.
wget https://raw.githubusercontent.com/humanoid-path-planner/hpp_tutorial/refs/heads/devel/tutorial_1/Dockerfile
  1. Download a lightweight web browser
wget https://github.com/goastian/midori-desktop/releases/download/v11.6/midori_11.6-1_amd64.deb
  1. Build the docker image
docker build --build-arg DOCKER_USER=`id -u` --build-arg DOCKER_GROUP=`id -g` -t hpp:tuto -f Dockerfile .
  1. Create directory src
mkdir src
  1. get configuration file and compilation file
wget https://raw.githubusercontent.com/humanoid-path-planner/hpp_tutorial/refs/heads/devel/tutorial_1/config.sh
wget -O src/Makefile https://raw.githubusercontent.com/humanoid-path-planner/hpp_tutorial/refs/heads/devel/tutorial_1/Makefile
  1. Get script that will run docker
wget https://raw.githubusercontent.com/humanoid-path-planner/hpp_tutorial/refs/heads/devel/tutorial_1/run_docker.sh
  1. Run the container
chmod 775 run_docker.sh
./run_docker.sh
  1. In the docker container, install a few things.
cd /home/user/devel/src
make all

Everything is now installed. You can now exit the container by typing CTRL-D and proceed to tutorial 2.

Note

The docker container shares the current directory in your host machine with /home/user/devel. As a consequence, if you restart it later, you do not need to redo the previous steps.

Solving a simple pick and place task with HPP

This tutorial will help you defining and solving a simple pick and place task with a franka robot.

Prerequisite

Having installed HPP by following the steps described in tutorial 1.

Resources

The main concepts and theory implemented in HPP software are described in the following paper: https://laas.hal.science/hal-02995125v2.

You can access the C++ online API documentation here

Starting the container and opening new terminals

To open again the container, in the same directory as in tutorial 1, simply run the command

./run_docker.sh

Then in another terminal, type

docker exec -it hpp bash

This will open another bash terminal in the container. You can do this as many times as you want to open new terminals in the container.

In the new terminal, open midori web browser:

midori

Building and displaying a robot

In the first terminal, go into directory hpp_tutorial/tutorial_2 and run the following python script

cd /home/user/devel/src/hpp_tutorial/tutorial_2
python -i init.py

You are now in an interactive python terminal. To display the robot that has been loaded by the script, type

v = Viewer(robot)
v.initViewer(open=False, loadModel=True)
v(q)

Then in midori address bar, type http://localhost:8080. You should see the panda robot.

You can have a quick look at the script to see the instructions used to define the robot.

Adding an obstacle to the scene

In the python terminal, copy-paste the following instructions

urdf_filename = "package://hpp_tutorial/urdf/ground.urdf"
srdf_filename = "package://hpp_tutorial/srdf/ground.srdf"
urdf.loadModel(robot, 0, "ground", "anchor", urdf_filename, srdf_filename, SE3.Identity())
v = Viewer(robot)
v.initViewer(open=False, loadModel=True)
v(q)

Adding an object to the scene

In the python terminal, copy-paste the following instructions

urdf_filename = "package://hpp_tutorial/urdf/box.urdf"
srdf_filename = "package://hpp_tutorial/srdf/box.srdf"
urdf.loadModel(robot, 0, "box", "freeflyer", urdf_filename, srdf_filename, SE3.Identity())
q = neutral(robot.model())
q[7:9] = [0.035, 0.035]
q[9:12] = [.4, -0.2, 0.025]
v = Viewer(robot)
v.initViewer(open=False, loadModel=True)
v(q)

Setting bounds to the object translation

Latter on, we will uniformly sample random configurations. To make it possible, we need to set bounds to the translation of the object.

robot.setJointBounds("box/root_joint", [-1.5, 1.5,
    -1.5, 1.5,
    -0.2, 1.5,
    -float("Inf"), float("Inf"),
    -float("Inf"), float("Inf"),
    -float("Inf"), float("Inf"),
    -float("Inf"), float("Inf")])

The first six values are the minimal and maximal values along x, y, z axes. The eight last values apply to the quaternion coefficients that need not being bounded.

Explaining the code

Let us have a quick look at the code in init.py.

robot = Device("tuto")

This line creates an empty robot implementing

  • a pinocchio model for the kinematic chain,
  • a pinocchio geometric model for collision, and
  • a pinocchio geometric model for visual display.

The following lines populate the kinematic chain with a panda robot:

urdf_filename = "package://example-robot-data/robots/panda_description/urdf/panda.urdf"
srdf_filename = "package://hpp_tutorial/srdf/panda.srdf"

urdf.loadModel(robot, 0, "panda", "anchor", urdf_filename, srdf_filename, SE3.Identity())

The arguments of the latter functions are the following:

  • robot: the kinematic chain to which the new robot will be appended,
  • 0: the index of the frame to which the new robot is appended (here the world frame),
  • "anchor": the type of mobility of the new robot base_link (here the robot is fixed to the environment),
  • urdf_filename: URDF file that describes the new robot,
  • srdf_filename: SRDF file that adds some information about the new robot, like collision pairs, and some information we will explain later on,
  • SE3.Identity() pose of the new robot in the world frame.

The following lines of code retrieve the neutral configuration of the robot (all joint set to 0) and open the gripper of the panda.

# Get neutral configuration of robot
q = neutral(robot.model())
# Open the gripper
q[-2:] = [0.035, 0.035]

Note that adding the ground and a box use the same function. The box is added with “freeflyer” as the mobility type. Therefore, the box is part of the kinematic chain and neutral returns a vector of dimension 16 (9 for the panda, 7 for the box).

Explaining the SRDF files

SRDF follows the xml syntax. Some specific tags are parsed by HPP to add information to the robot and object models. Let us now have a look at the srdf files that are used above by function urdf.loadModel Note that all srdf files used above can be found in the srdf directory of the package.

In file panda.srdf,

    <!-- gripper -->
    <gripper name="gripper" clearance="0.05">
      <position xyz="0 0 0" wxyz="1 0 0 0" />
      <link name="panda_hand_tcp"/>
    </gripper>

defines a gripper, that is a frame attached to link panda_hand_tcp. The relative pose of the frame with respect to the link is defined by tag position. Attribute xyz defines the translation, attribute wxyz defines the rotation as a unit quaternion with real part in first position. Attribute clearance will be used later on to define pregrasp configurations.

In file box.srdf,

  <handle name="handle" clearance="0.025" approaching_direction="0 0 1">
    <position xyz="0 0 0" wxyz="0 0 1 0" />
    <link name="base_link"/>
  </handle>

defines a handle, that is a frame attached to link base_link. he relative pose of the frame with respect to the link is defined by tag position. Note that the z axis of the handle points downwards when the object is placed on a horizontal contact surface. Tag approaching_direction will be used by used later on by the constraint graph factory to generate pregrasp states.

  <contact name="surface">
    <link name="base_link"/>
    <point>-0.025 -0.025 -0.025   -0.025 0.025 -0.025   0.025 0.025 -0.025   0.025 -0.025 -0.025
    </point>
    <shape> 4 0 1 2 3</shape>
  </contact>

defines a contact surface used to define stable poses of the object. The surface is a plane polygon defined by the vertices (point tag). Here we define 1 polygon with 4 vertices in order 0 1 2 3 (shape tag).

Note that box.srdf also defines a contact surface. The box is in stable contact pose when the contact surfaces are coplanar with opposite normal and the center of the box surface is included in the polygonal surface of the ground.

A quick tour of the viewer

In the upper right corner of the viewer, there is the following window to control the view. We call this window the view controller.

Move the mouse to the icon representing three vertical sliders in the upper right corner, “Configuration and diagnostics” should pop up. Click on the icon and you will see the scene tree. Clicking again brings you back to the initial widget. Select tab “Display” in the upper part of the view controller and select “Show Visuals”, “Show Frames” and “Show Contact Surfaces”. Many frames are displayed, as well as the contact surfaces defined in the SRDF files.

Go again to the scene tree. In the tree, expand “pinocchio” then “frames”, then “panda”. By clicking on the eye in front of each node, you remove the corresponding frame from the view. Remove them all except “panda/gripper” and “box/handle”. You now see the gripper and handle frames that will define how the robot grasps the object as in the picture below.

Defining a manipulation problem

The manipulation problem is defined through a variable of type Problem and through the constraint graph that will be constructed by a factory. Let us define those variables.

from pyhpp.manipulation import (Graph, Problem, ManipulationPlanner)
from pyhpp.manipulation.constraint_graph_factory import ConstraintGraphFactory

problem = Problem(robot)
graph = Graph("robot", robot, problem)
factory = ConstraintGraphFactory(graph)

Later on the graph will solve numerical constraints. We need to set the error threshold and the maximal number of iterations.

graph.maxIterations(40)
graph.errorThreshold(1e-5)

Then, we need to define the set of grippers that will be used.

factory.setGrippers(["panda/gripper"])

We also define the list of objects and for each of them, the list of handles and the list of contact surfaces.

objects = ["box"]
handlesPerObject = [["box/handle"]]
contactsPerObject = [["box/surface"]]
factory.setObjects(objects, handlesPerObject, contactsPerObject)

Finally, we define the set of environment contact surfaces (surfaces on which objects may be placed).

factory.environmentContacts(["ground/surface"])

Then we ask the factory to generate the constraint graph corresponding to the manipulation problem.

factory.generate()

Before initializing the graph, we will add a constraint to all states and transitions in order to keep the gripper open all the time.

import numpy as np
from pyhpp.constraints import (ComparisonType, ComparisonTypes, LockedJoint)
cts = ComparisonTypes()
cts[:] = [ComparisonType.EqualToZero]
lockedFingers = list()
for i in range(2):
    lj = LockedJoint(robot, f'panda/panda_finger_joint{i+1}', np.array([0.035]), cts)
    lockedFingers.append(lj)

graph.addNumericalConstraintsToGraph(lockedFingers)
graph.initialize()

Displaying the constraint graph

In the python terminal, copy paste the following lines

v.setProblem(problem)
v.setGraph(graph)

In the view controller, click on the button “Show Graph Viewer”. The window below should appear.

This window displays the constraint graph.

If you click on show waypoints, you will see waypoint states as on the picture below. Those intermediate states ease manipulation planning by forcing the robot to approach the object from above and lift it above the ground before moving it. The distance of the gripper to the object in pregrasp state is the sum of the gripper and handle clearances defined in the SRDF files.

By clicking on a state, you can display the constraints of this state. By right clicking on a state, you can select “Generate random config” and figure out what the additional states are meant for. Note that this operation may fail if the numerical solver does not converge and that it does not care for collisions.

Back to the manipulation problem

To define a manipulation problem, we now simply need to set the initial and goal configurations. To do so, we move the robot in a collision-free configuration and change only the pose of the box between those configurations

q_init = np.array([ 0.   ,  0.   ,  0.   , -0.5  ,  0.   ,  0.5  ,  0.   ,  0.035,
        0.035,  0.4  , -0.2  ,  0.0251,  0.   ,  0.   ,  0.   ,  1.   ])
q_goal = np.array([ 0.   ,  0.   ,  0.   , -0.5  ,  0.   ,  0.5  ,  0.   ,  0.035,
        0.035,  0.4  ,  0.2  ,  0.0251,  0.   ,  0.   ,  0.   ,  1.   ])

You can display these configurations with

v(q_init)
v(q_goal)

Solving the manipulation problem

To define and solve the problem,

from pyhpp.manipulation import ManipulationPlanner
problem.initConfig(q_init)
problem.addGoalConfig(q_goal)
problem.constraintGraph(graph)
manipulationPlanner = ManipulationPlanner(problem)
manipulationPlanner.maxIterations(500)
p = manipulationPlanner.solve()

Displaying the resulting path

You can display the resulting path in the graphical interface by first loading it

v.loadPath(p)

and then by clicking on “Play” in the view controller.

optimizing paths

Random sampling method usually compute paths that are far from being optimal. These paths can be post-processed to make them shorter.

from pyhpp.core import RandomShortcut
optimizer = RandomShortcut(problem)
p1 = optimizer.optimize(p)

How to use HPP in manufacturing.

Prerequisite

Having installed HPP by following the steps described in tutorial 1.

Introduction

In many manufacturing applications, we often need to bring a tool mounted on a robot end effector to a predefined pose with respect to a part. This tutorial shows how to use the same concepts as in tutorial 2 to perform a simplified drilling task.

Initializing the problem

In the docker container, cd into tutorial_3 directory. In a bash terminal, run

python -i init.py

to load the models and initialize the path planning problem. The script is similar to tutorial_2 example, except that

  • the robot is a Stäubli TX2-90 holding a drill,
  • the object is a vertical square plate,
  • a function display() creates and initializes the viewer client,
  • a handle is added to the object via python and not via the SRDF file.

The handle is created and added by the following lines

# Add a handle on the plate
R = np.array([[ 0, 0, 1],
              [ 0, 1, 0],
              [-1, 0, 0]])
T = np.array([0.02, 0, 0])
pose = SE3(rotation = R, translation = T)
robot.addHandle("plate/base_link", "plate/hole", pose, 0.1, 6*[True])
handle = robot.handles()["plate/hole"]
handle.approachingDirection = np.array([0, 0, 1])

the pose of the handle in the link frame is provided by an object of type SE3 from pinocchio module, initialized by a rotation matrix and a translation vector. Note that the link name and the handle names are prefixed by the name of the object that holds the handle: "plate/base_link", "plate/hole". Parameter 0.1 is the handle clearance.

The code above is equivalent to the following lines in an SRDF file:

  <handle name="hole" clearance="0.1" approaching_direction="0 0 1">
    <position xyz="0.02 0 0" rpy="0 1.5707963267948966 0" />
    <link name="base_link"/>
  </handle>

Creating waypoint configurations

To plan a drilling motion, we will proceed in several steps:

  1. generate a “pregrasp” (qpg) and a “grasp” (qg) configurations,
  2. plan motions between q_init and qpg, then plan a motion between qpg and qg.

For step 1, first copy paste the following code into the python terminal:

# Generate configuration in pregrasp reachable from q_init and in grasp reachable from pregrasp
transition = graph.getTransition("staubli/tooltip > plate/hole | f_01")
pv = transition.pathValidation()
res, qpg, err = graph.generateTargetConfig(transition, q_init, q_init) # -> failure
if not res:
    print ("Failed to project q_init to pregrasp waypoint state")

The above code tries to project configuration q_init to the pregrasp waypoint state “staubli/tooltip > plate/hole | f_pregrasp”. Method graph.generateTargetConfig uses a solver containing the constraints of transition “staubli/tooltip > plate/hole | f_01” and of the target state “staubli/tooltip > plate/hole | f_pregrasp”. In this case the constraints are

  • Locked joint “plate/root_joint”,
  • staubli/tooltip pregrasps plate/hole.

The right hand side of the first one is initialized with q_init (second argument). This simply means that the part shoud be in the same pose as in q_init. The second one is a constraint of relative pose between the gripper and the handle: both frames should have the same orientation and the position of the center of the handle in the gripper frame is the product of the sum of gripper and handle clearances by the approaching direction vector. As state above, the solver is initialized with q_init (third argument). The output of the function is composed of

  • res: True if the solver succeeded, False otherwise,
  • qpg: the result configuration or the last iteration of the solver in case of failure,
  • err: the norm of the residual.

Note that projection fails, this does not mean that the constraints have no solution. Initializing the solver with another configuration may succeed.

Copy paste now the code below in the python terminal.

for i in range(1000):
    transition = graph.getTransition("staubli/tooltip > plate/hole | f_01")
    q = shooter.shoot()
    res, qpg, err = graph.generateTargetConfig(transition, q_init, q)
    if not res: continue
    res, report = pv.validateConfiguration(qpg)
    if not res: continue
    transition = graph.getTransition("staubli/tooltip > plate/hole | f_12")
    res, qg, err = graph.generateTargetConfig(transition, qpg, qpg)
    if res: break

# Notice that qg is in collision
res, report = pv.validateConfiguration(qg)
print(report)

The code above tries to generate a pregrasp and a grasp configurations by initializing the pregrasp solver with a random configuration and the grasp solver with the pregrasp configuration. The pregrasp configuration is tested for collision. If a projection fails or a collision occurs, the loop restart with another random configuration. Note that the grasp configuration is produced by initializing the solver (second call to graph.generateTargetConfig) with the pregrasp configuration. This is necessary to make sure that the latter is close to the former and that the robot does not need a long reconfiguration motion to reach grasp from pregrasp.

You can visualize qpg and qg in the graphical interface as follows.

v = display()
v(q_init)
v(qpg)
v(qg)

Using security margins

In the previous example, the grasp configuration is in collision since the tool is inside the part. We need to deactivate collision checking between the end-effector and the part on the second part of the motion (transition “staubli/tooltip > plate/hole | f_12”). For that, we will use a python class to handle security margins.

A security margin is a distance below which two objects are considered as colliding. By extension,

  • a negative security margin means that penetration is allowed
  • -Inf security margin means that the object are never considered as colliding.

Path and configurations are checked for collisions by PathValidation instances. Each transition of the constraint graph owns a PathValidation (hpp::core::ContinuousValidation) instance. Security margins can be defined between pairs of joints by a square matrix of size the number of joints. The value in a cell corresponds to the security margin between the joints corresponding to the row and column indices of the cell. the indices are those in the list returned by

robot.getJointNames()

The code below sets security margins between robots (as set of joints). Copy paste the code in the python terminal

# Defining security margins
from pyhpp.manipulation.security_margins import SecurityMargins
sm = SecurityMargins(problem,factory, ["staubli", "plate"], robot)
sm.setSecurityMarginBetween("staubli", "plate", 0.05)
sm.apply()

Then, if you type

M = graph.getSecurityMarginMatrixForTransition(transition)
print(np.array(M))

you should see

[[0.   0.   0.   0.   0.   0.   0.   0.  ]
 [0.   0.   0.   0.   0.   0.   0.   0.05]
 [0.   0.   0.   0.   0.   0.   0.   0.05]
 [0.   0.   0.   0.   0.   0.   0.   0.05]
 [0.   0.   0.   0.   0.   0.   0.   0.05]
 [0.   0.   0.   0.   0.   0.   0.   0.05]
 [0.   0.   0.   0.   0.   0.   0.   0.05]
 [0.   0.05 0.05 0.05 0.05 0.05 0.05 0.  ]]

and notice that between each joint of the robot and the plate, the security margin is 0.05.

The following code deactivates collision checking between the robot end effector and the plate along a transition.

transition = graph.getTransition("staubli/tooltip > plate/hole | f_12")
graph.setSecurityMarginForTransition(transition, "staubli/joint_6", "plate/root_joint",
                                     float("-inf"))

Copy paste this code and display again the security margin matrix.

After modifying the graph, we need to reinitialize it.

graph.initialize()

We can now generate collision free pregrasp and grasp configurations.

# Generate configuration in pregrasp reachable from q_init and in grasp reachable from pregrasp
# and test collision for both.
for i in range(1000):
    # Project random configuration on pregrasp waypoint state
    transition = graph.getTransition("staubli/tooltip > plate/hole | f_01")
    q = shooter.shoot()
    res, qpg, err = graph.generateTargetConfig(transition, q_init, q)
    if not res: continue
    # Check the configuration for collision
    pv = transition.pathValidation()
    res, report = pv.validateConfiguration(qpg)
    if not res: continue
    # Project pregrasp configuration on grasp state
    transition = graph.getTransition("staubli/tooltip > plate/hole | f_12")
    res, qg, err = graph.generateTargetConfig(transition, qpg, qpg)
    if not res: continue
    # Check the configuration for collision
    pv = transition.pathValidation()
    res, report = pv.validateConfiguration(qg)
    if res: break

You can visualize qpg and qg in the graphical interface.

Planning motions between the waypoint configurations

We now need to plan a motion between q_init and qpg and between qpg and qg, keeping the relevant constraints satisfied. Here the only relevant constraint is that the part should not move. To do so, we will use the TransitionPlanner class. This class plans motions along a transition, keeping the constraints of the transition satisfied. The right hand side of the parameterizable constraints of the transition is initialized with the initial configuration. The code below shows how to use this class.

from pyhpp.manipulation import TransitionPlanner
planner = TransitionPlanner(problem)
planner.maxIterations(1000)
for i in range(10):
    # Project random configuration on pregrasp waypoint state
    transition = graph.getTransition("staubli/tooltip > plate/hole | f_01")
    q = shooter.shoot()
    res, qpg, err = graph.generateTargetConfig(transition, q_init, q)
    if not res: continue
    # Check the configuration for collision
    pv = transition.pathValidation()
    res, report = pv.validateConfiguration(qpg)
    if not res: continue
    # plan motion between q_init and qpg
    planner.setTransition(transition)
    try:
        q_goal = np.zeros((robot.configSize(), 1))
        q_goal[:,0] = qpg
        p1 = planner.computePath(q_init, q_goal, True)
    except Exception as exc:
        print(f"path planning failed between q_init and qpg: {exc}")
        continue
    # Project pregrasp configuration on grasp state
    transition = graph.getTransition("staubli/tooltip > plate/hole | f_12")
    res, qg, err = graph.generateTargetConfig(transition, qpg, qpg)
    if not res: continue
    # Check the configuration for collision
    pv = transition.pathValidation()
    res, report = pv.validateConfiguration(qg)
    if not res: continue
    # plan motion between qpg and qg
    planner.setTransition(transition)
    try:
        q_goal = np.zeros((robot.configSize(), 1))
        q_goal[:,0] = qg
        p2 = planner.computePath(qpg, q_goal, True)
    except Exception as exc:
        print(f"path planning failed between qpg and qg: {exc}")
        continue
    if p2:
        p3 = p2.reverse()
        break

You can now load paths p1, p2, p3 in the graphical interface and play them.

v.loadPath(p1)
v.loadPath(p2)
v.loadPath(p3)

The drilling path is a little bit naive since the tool trajectory is not a straight line but the result of an interpolation in joint space and the velocities of the robot and tool are not controlled.

Tutorial 4 shows how to better control a tool trajectory.

How to control the trajectory of a tool.

Prerequisite

Having completed tutorial 3

Initializing the problem

In the docker container, cd into tutorial_4 directory. In a bash terminal, run

python -i init.py

The script contains the code of tutorial_3 up to the computation of a path to qpg. To plan a path between qpg and qg, we first generate a desired trajectory of the tooltip.

from pyhpp.constraints import (ComparisonType, ComparisonTypes)

gripper = robot.grippers()["staubli/tooltip"]
trajConstraint = handle.createGrasp(gripper, "drilling")
cts = ComparisonTypes()
cts[:] = 6*[ComparisonType.Equality]
trajConstraint.comparisonType(cts)
init = trajConstraint.function()(qpg)
goal = np.array([0,0,0,0,0,0,1])

The code above create a relative pose contraint between the gripper (tooltip) and the handle. The value of the constraint in SE(3) is the pose of the handle in the frame of the gripper. init is the value of the function in qpg. As an element of SE(3), it is not a vector.

print(init.space())

As shown in the python terminal, it is an element of R^3^ x SO(3) (equivalent to SE(3)). We can access to the vector representation as follows:

print(init.vector())

As expected, this corresponds to the pose of the handle in the gripper frame in configuration qpg: a translation of 10cm along z.

See documentation of class hpp::pinocchio::LiegroupSpace for more information.

from pyhpp.manipulation.steering_method import (Cartesian, makePiecewiseLinearTrajectory)

weights = 50*np.ones(6)
points = np.zeros(14).reshape((2,7))
points[0:] = init.vector()
points[1:] = goal
rhs = makePiecewiseLinearTrajectory(points, weights)

The above code creates a straight path in SE(3) from the initial pose of the gripper to the handle. The duration of the path is tuned by a vector of weights as described in the documentation of method hpp::manipulation::steeringMethod::Cartesian::makePiecewiseLinearTrajectory.

cartesian = Cartesian(planner.innerProblem())
cartesian.trajectoryConstraint = trajConstraint
cartesian.setRightHandSide(rhs, True)
res, p2 = cartesian.planPath(qpg)

The trajectory constraint as well as the time-varying right hand side are passed to the Cartesian steering method and a path is computed.

transition = graph.getTransition("staubli/tooltip > plate/hole | f_12")
pv = transition.pathValidation()
res, p3, report = pv.validate(p2, False)

The path is then tested for collision after setting the relevant security margins.

Tutorial 5 shows how to optimize and time-parameterize paths.

How to optimize and time-parameterize paths.

Prerequisite

Having completed tutorial 4

Initializing the problem

In the docker container, cd into tutorial_5 directory. In a bash terminal, run

python -i init.py

The script contains the code of tutorial 4 with an additional obstacle placed between the robot and the plate. This forces the planner to find a non-straight path for p1 (the motion from q_init to the pregrasp configuration qpg).

The path p1 uses a dimensionless path parameter s ranging from 0 to p1.length(). This parameter does not correspond to real time: the robot has no notion of velocity or acceleration along this path.

Visualizing the raw path

A small helper in plot.py plots joint positions, velocities, and accelerations against the path parameter. It returns the matplotlib figure so you can inspect it interactively or save it:

from plot import plotTraj

fig = plotTraj(p1, 0, 7, order=2)
fig.show()

The raw path p1 is collision-free but typically jagged, with abrupt direction changes. The acceleration plot shows large spikes — this is what the rest of this tutorial smooths out.

Path optimization

Before time parameterization we smooth the path with SplineGradientBased_bezier3, which fits a cubic-Bézier spline that minimizes integral squared acceleration while remaining collision-free:

from pyhpp.core import SplineGradientBased_bezier3

bezier = SplineGradientBased_bezier3(problem)
p2 = bezier.optimize(p1)
print(f"Smoothed path length: {p2.length():.3f} (was {p1.length():.3f})")

The resulting path is continuously differentiable (C1), a prerequisite for producing a smooth velocity profile in the next step.

Time parameterization

TOPPRA

TOPPRA (Time-Optimal Path Parameterization based on Reachability Analysis) computes the time-optimal parameterization subject to velocity, acceleration, and torque constraints. Applied directly to the raw path p1, TOPPRA produces endpoint velocity discontinuities and an acceleration spike at the start. Applied after SplineGradientBased_bezier3, the smoothed spline eliminates these and keeps accelerations bounded throughout. Note that the acceleration bounds apply only on selected joints. Below, we select only the robot joints.

import numpy as np
from pyhpp_toppra import Toppra

toppra = Toppra(problem)
toppra.velocityScale = 0.5
toppra.effortScale = -1
toppra.N = 100
toppra.selectJoints([f"staubli/joint_{i}" for i in range(1,7)])
toppra.accelerationLimits = np.array(6 * [0.5])
p3 = toppra.optimize(p2)
print(f"TOPPRA duration: {p3.length():.3f} s")

Parameters:

  • velocityScale: scaling factor for velocity limits (1.0 = full velocity). Use a small value (e.g. 0.5) for slower, more visible motions.
  • effortScale: scaling factor for torque limits. Set to a negative value to disable torque constraints. Note: torque constraints require mass and inertia data in the robot URDF. The Staubli model has no dynamics data, so effortScale must be set to -1 (disabled).
  • accelerationLimits: per-DOF acceleration cap. The vector size must match the problem’s velocity dimension, not the configuration size — here it is 6 (6-DOF Staubli arm).
  • N: minimal number of discretization points along the path.
  • interpolationMethod: "constant_acceleration" or "hermite".
  • gridpointMethod: "param_space" or "time_space".

Compare the profiles after Bézier smoothing and after optimal time parameterization:

fig = plotTraj(p2, 0, 7, order=2)
fig.show()
fig = plotTraj(p3, 0, 7, order=2)
fig.show()

SimpleTimeParameterization (simpler alternative)

When hpp-toppra is not available, SimpleTimeParameterization computes a polynomial time parameterization that maps real time t to the path parameter s, while respecting joint velocity and acceleration limits. It is less optimal than TOPPRA but needs no extra dependency.

from pyhpp.core import SimpleTimeParameterization

stp = SimpleTimeParameterization(problem)
stp.order = 2
stp.safety = 0.95
stp.maxAcceleration = 0.5
p_stp = stp.optimize(p2)
print(f"STP duration: {p_stp.length():.3f} s")

Parameters:

  • order: polynomial continuity order. 0 = linear (C0), 1 = cubic (C1, zero velocity at endpoints), 2 = quintic (C2, zero velocity and acceleration at endpoints).
  • safety: scaling factor for velocity limits (0.95 = use 95% of max velocity).
  • maxAcceleration: maximum acceleration per DOF in rad/s². Only used when order >= 2. Set to a negative value to disable.

Visualization

You can visualize the path in the viewer:

v = display()
v.loadPath(p3)

How to use a rviz2 visualization

Prerequisite

Having completed tutorial 2.

Overview

This tutorial shows how to set up an RViz2 visualization for HPP using the RVizVisualizer from pyhpp_rviz. Unlike the web-based viewer used in tutorials 2–5, this visualizer communicates over ROS 2 topics and displays the robot, paths, and landmarks directly inside RViz2.

Setting up the simulation

The base tutorial docker image does not include ROS 2 control packages. Build the extended image from the tutorial 6 directory on the host machine (not inside the container):

cd tutorial_6
docker build --build-arg DOCKER_USER=`id -u` --build-arg DOCKER_GROUP=`id -g` \
    -t hpp-ros2:tuto .

Then start the container from the root shared directory:

cd ../../..
./src/hpp_tutorial/tutorial_6/run_docker.sh

Compiling the HPP RViz2 plugins

On your first make all from tutorial 1, the RViz2 plugin sources were notcompiled. Build hpp-rviz:

cd src
make hpp-rviz.install

export the package path

export ROS_PACKAGE_PATH=/home/user/devel/src/:/opt/openrobots/share/:$ROS_PACKAGE_PATH

Initializing the viewer

In the docker container, cd into tutorial_6 directory and run:

python -i init.py

The script is identical to tutorial 2 up to the computation of path p The only difference is that it uses RVizVisualizer instead of viser Viewer.

from pyhpp_rviz import RVizVisualizer as Viewer

v = Viewer()
v.initViewer(robot=robot)

Configuring RViz2

Open a second terminal in the container:

docker exec -it hpp bash
rviz2

In RViz2, set the Fixed Frame to world (in the Global Options panel).

Set the Frame Rate to 300

For each model loaded with urdf.loadModel, add a RobotModel display and set its Description Topic to the topic published for that model (e.g. /panda/robot_description, /ground/robot_description, /box/robot_description). The prefix matches the name passed to urdf.loadModel.

Add a TF display to visualize all frame transforms published by the viewer.

Disable TF arrows and put Frame Time Out to 1e+07

There is a rviz config file on hpp_tutorial/launch/tuto6.rviz

rviz2 -d hpp_tutorial/launch/config.rviz

Call v(q_init) in the Python terminal to place all objects in their initial configuration. The scene should now appear in RViz2.

Visualizing a configuration

v(q_init)

Use v(config) to display a configuration on rviz2 like is done with viser.

Visualizing a path

Add the Trajectory plugin (from the HPP RViz2 plugins) to RViz2. A control panel will appear at the bottom of the screen.

Load a path from the Python terminal:

v.loadPath(path)

The panel lets you slide through the path parameter to inspect any intermediate configuration.

To display the spatial trace of a frame along the path, use:

v.displayPath(path, target_frame="panda/gripper")

You can also trigger this from RViz2 by entering the frame name directly in the DisplayTrajectory panel.

Adding landmarks

Add the Landmark tool from the RViz2 toolbar (installed with the HPP RViz2 plugins). Add the Landmark display to visualize the landmarks in the scene.

Landmarks can be placed in three ways:

  • Interactively: select the Landmark tool in the toolbar, then click in the 3D view. Drag the landmark with the interact tool for moving it or Right-click a landmark marker and choose Edit position to adjust it numerically with the interact tool too

  • From a named frame (Python):

    v.addLandmarkFromFrame("panda/gripper", "first landmark")
    

    This publishes the current pose of the given frame as a landmark.

  • From explicit coordinates (Python):

    v.addLandmark(xyz=[0.8, 0.0, 1.0], quat_xyzw=[0.0, 0.0, 0.0, 1.0], "landmark")
    

Summary of viewer methods

MethodDescription
v(q)Display configuration q
v.loadPath(p)Register path p for trajectory control
v.displayPath(p, target_frame=...)Publish the spatial trace of a frame along p
v.addLandmarkFromFrame(frame)Publish current pose of frame as a landmark
v.addLandmark(xyz, quat_xyzw)Publish an explicit pose as a landmark
v.setProblem(problem)Register problem for graph viewer
v.setGraph(graph)Register constraint graph for graph viewer
v.launch_graph_viewer()Open the constraint graph viewer (React app)

How to execute motions on a simulated robot.

Prerequisite

Having completed tutorial 6.

Overview

This tutorial plans a simple arm motion for the Franka FR3 robot and executes it on a Gazebo simulation via ROS2. It introduces the hpp_exec package which bridges HPP paths to ros2_control.

Terminal 1: Launching the simulation

Launch the Gazebo simulation with a joint_trajectory_controller:

ros2 launch hpp_tutorial tutorial_6_launch.py

Wait until you see Configured and activated joint_trajectory_controller in the output.

Terminal 2: Planning and executing

Open a second terminal:

docker exec -it hpp bash

Source the environments and run the tutorial script:

cd ~/devel/src/hpp_tutorial/tutorial_6
python -i init.py

The script loads the FR3 robot, plans a motion from the current robot configuration to a goal configuration using BiRRT, optimizes it with RandomShortcut, and applies time parameterization using SimpleTimeParameterization (as seen in tutorial 5).

You can visualize the planned path in the browser viewer:

v = display()
v.loadPath(p_timed)

Understanding the trajectory

After time parameterization, p_timed is a continuous function mapping time (in seconds) to robot configurations. To send it to ros2_control, we need discrete waypoints.

Check the trajectory duration:

print(f"Trajectory duration: {p_timed.length():.2f} seconds")

Sample a configuration at a specific time (e.g., t=1.0s):

q, success = p_timed(1.0)
print(f"Config at t=1.0s: {q}")  # First 7 values are arm joints

The HPP configuration vector has 9 elements: 7 arm joints + 2 finger joints.

Extracting waypoints

To execute the trajectory, we sample it at regular intervals. Try extracting waypoints yourself:

import numpy as np

n_samples = 50
configs = []
times = []

for i in range(n_samples + 1):
    t = (i / n_samples) * p_timed.length()
    q, success = p_timed(t)
    assert(success)
    configs.append(np.array(q))
    times.append(t)

print(f"Extracted {len(configs)} waypoints over {times[-1]:.2f} seconds")

Sending the trajectory

Now send the waypoints to Gazebo via ros2_control:

from hpp_exec import send_trajectory

send_trajectory(
    configs, times,
    joint_names=[f'fr3_joint{i}' for i in range(1, 8)],
    joint_indices=list(range(7)),
)
  • joint_names: The ROS2 joint names expected by the controller.
  • joint_indices: Which elements of the HPP config to send (indices 0-6 are the arm joints; we skip indices 7-8 which are the fingers).

You should see the robot move in Gazebo and Trajectory execution complete in the terminal.

Experiment

Try different values of n_samples (e.g., 10, 100, 200) and observe how it affects the smoothness of motion in Gazebo.

You can also play the reverse motion using

p_reversed = p_timed.reverse()

Pick and place with gripper, introducing pre and post-actions

Prerequisite

Having completed tutorial 7.

Overview

Tutorial 6 executed one arm trajectory with send_trajectory. This tutorial adds the gripper: the robot must open the fingers before approaching the box, close them before transport, then open them again at the goal.

The script plans a pick-and-place path with an HPP manipulation constraint graph. We then use hpp_exec to expose the graph segments, attach the Gazebo actions for this problem, and execute the segments.

For the full hpp_exec API, see the hpp-exec documentation.

Setting up the simulation

Use the same Docker image as tutorial 6 (hpp-ros2:tuto). If you have not built it yet, see the tutorial 6 instructions.

Terminal 1: Launching the simulation

Launch Gazebo with the FR3 and its gripper:

ros2 launch hpp_tutorial tutorial_7_launch.py

Wait until you see Configured and activated gripper_controller in the output.

Note: one gripper finger may appear loose in Gazebo. This is a simulation artefact with mimic joints. It does not affect the tutorial.

Terminal 2: Planning

Open a second terminal:

docker exec -it hpp bash

Run the tutorial script:

cd ~/devel/src/hpp_tutorial/tutorial_7
python -i init.py

The script loads the FR3, the ground, and a box. It solves a pick-and-place problem that moves the box from (0.4, -0.2) to (0.4, 0.2), optimizes the path, time-parameterizes it with SimpleTimeParameterization.

Note that between optimization and time parameterization, an object called EnforceTransitionSemantic is called. This steps labels each sub-path with the transition of the graph the sub-path belongs to. This step is necessary before executing the path in order to place pre-actions and post-actions at the right times.

You can visualize the planned path in the browser viewer:

v = display()
v.loadPath(p_timed)

Defining gripper actions

Create the actions that will be called during execution:

from hpp_exec import send_trajectory


def attach_box():
    attach_pub.publish(Empty())
    rclpy.spin_once(gazebo_node, timeout_sec=0.05)
    time.sleep(0.2)
    gazebo_node.get_logger().info("Published '/box/attach' on Gazebo topic")
    return True


def detach_box():
    detach_pub.publish(Empty())
    rclpy.spin_once(gazebo_node, timeout_sec=0.05)
    time.sleep(0.2)
    gazebo_node.get_logger().info("Published '/box/detach' on Gazebo topic")
    return True


def open_gripper():
    return send_trajectory(
        [np.array([0.0]), np.array([0.035])],
        [0.0, 0.5],
        joint_names=GRIPPER_JOINT_NAMES,
        controller_topic="/gripper_controller/follow_joint_trajectory",
    )


def close_gripper():
    return send_trajectory(
        [np.array([0.035]), np.array([0.0])],
        [0.0, 0.5],
        joint_names=GRIPPER_JOINT_NAMES,
        controller_topic="/gripper_controller/follow_joint_trajectory",
    )


def grasp_box():
    return attach_box() and close_gripper()


def release_box():
    return open_gripper() and detach_box()

open_gripper and close_gripper send a reference value for fr3_finger_joint1 to open or close the gripper. They use send_trajectory, as in tutorial_6. On the real robot, this would be performed by a ROS action instead.

grasp_box and release_box call attach_box and detach_box respectively. These functions tell Gazebo that the box is attached to or detached from the end effector.

At this point the useful objects are:

  • p_timed: the time-parameterized HPP path.
  • configs: sampled HPP configurations along the timed path.
  • times: timestamps in seconds, returned by segments_from_graph.
  • segments: graph segments where you can add pre/post actions.
  • graph: the HPP manipulation constraint graph.
  • open_gripper, close_gripper, grasp_box, and release_box: Gazebo actions for the gripper and simulated box attachment.

Building execution segments

The planned path contains the approach, transport, and retreat motion in one path. Ask hpp_exec to sample the timed path and expose the HPP graph segments:

from hpp_exec import segments_by_transition, print_segments, segments_from_graph

configs, times, segments = segments_from_graph(p_timed, graph)
print_segments(segments)

The table shows the segment times, graph transition names, nominal states, observed states, and how many pre/post actions are attached.

Build a transition-name map and attach the actions to the movements used in this tutorial:

GRASP_TRANSITION = "fr3/gripper > box/handle | f_23"
RELEASE_TRANSITION = "fr3/gripper < box/handle | 0-0_21"

segments_by_name = segments_by_transition(segments)

segments[0].pre_actions.append(open_gripper)
for segment in segments_by_name[GRASP_TRANSITION]:
    segment.pre_actions.append(grasp_box)
for segment in segments_by_name[RELEASE_TRANSITION]:
    segment.pre_actions.append(release_box)

print_segments(segments)

segments_by_transition is a dictionary that stores the segments by the transition they belong to. This is very convenient to assign pre or post-actions to each segment. Conceptually, execution has three phases:

#PhaseWhat the arm doesAction before phase
0approachmove above the box, descendopen
1transportcarry the box to the goalattach and close
2retreatlift and returnopen and detach

Executing the segments

Send the arm segments to the arm controller and let the segment actions command the gripper controller:

from hpp_exec import execute_segments

close_gripper()
reset_box_pose()
execute_segments(
    segments, configs, times,
    joint_names=[f"fr3_joint{i}" for i in range(1, 8)],
    joint_indices=list(range(7)),
)

You should see the fingers open, the arm descend, the fingers close on the box, the arm carry the box to the goal, the fingers open, and the arm retreat.

reset_box_pose() detaches the simulated box if needed and places it back at the planned start pose before execution.

A more efficient way to assign pre or post-actions

Prerequisite

Having completed tutorial 8.

Overview

Tutorial 7 opens the gripper as a blocking pre-action before the approach motion. This tutorial uses hpp_exec.BackgroundAction to start opening the gripper in the background, let the arm begin travelling, then wait for the opening action just before grasping the box.

The planning problem, Gazebo setup, and pick-and-place path are the same as in tutorial 7. Only the execution actions change.

For the full hpp_exec API, see the hpp-exec documentation.

Setting up the simulation

Use the same Docker image as tutorial 6 (hpp-ros2:tuto). If you have not built it yet, see the tutorial 6 instructions.

Terminal 1: Launching the simulation

Launch the same FR3 and gripper simulation as tutorial 7:

ros2 launch hpp_tutorial tutorial_7_launch.py

Wait until you see Configured and activated gripper_controller in the output.

Note: one gripper finger may appear loose in Gazebo. This is a simulation artefact with mimic joints. It does not affect the tutorial.

Terminal 2: Planning

Open a second terminal:

docker exec -it hpp bash

Run the tutorial script:

cd ~/devel/src/hpp_tutorial/tutorial_8
python -i init.py

The script loads the FR3, the ground, and a box. It solves the same pick-and-place problem as tutorial 7, optimizes the path, enforces transition semantics, and time-parameterizes it with SimpleTimeParameterization.

You can visualize the planned path in the browser viewer:

v = display()
v.loadPath(p_timed)

At this point the useful objects are:

  • p_timed: the time-parameterized HPP path.
  • configs: sampled HPP configurations along the timed path.
  • times: timestamps in seconds, returned by segments_from_graph.
  • segments: graph segments whose transition_name values can be used as action dictionary keys.
  • graph: the HPP manipulation constraint graph.
  • open_gripper, close_gripper, grasp_box, and release_box: Gazebo actions for the gripper and simulated box attachment.

Building execution dictionaries

The planned path contains the approach, transport, and retreat motion in one path. Ask hpp_exec to sample the timed path and expose the HPP graph segments:

from hpp_exec import segments_by_transition, print_segments, segments_from_graph

configs, times, segments = segments_from_graph(p_timed, graph)
print_segments(segments)

This tutorial attaches actions by graph transition name. First wrap the opening action so it can run while the arm starts moving:

from hpp_exec import BackgroundAction

background_open_gripper = BackgroundAction(open_gripper, name="open_gripper")

Set the transition names where the action dictionaries should apply, then check how many path occurrences use each transition:

APPROACH_TRANSITION = "Loop | f"
GRASP_TRANSITION = "fr3/gripper > box/handle | f_23"
RELEASE_TRANSITION = "fr3/gripper < box/handle | 0-0_21"

segments_by_name = segments_by_transition(segments)

Now fill the pre-action and post-action dictionaries. The keys are exact transition names, and the values are callables. A dictionary entry applies to every segment with that transition name, so check the printed table and the occurrence counts before executing. In this movement, each transition used below appears once. If a different movement repeats one of these names, the dictionary action would run for every occurrence; use segments_by_name[TRANSITION_NAME][i].pre_actions when you need to attach an action to one chosen occurrence.

pre_actions_by_transition = {
    APPROACH_TRANSITION: [background_open_gripper.start],
    GRASP_TRANSITION: [background_open_gripper.wait, grasp_box],
    RELEASE_TRANSITION: [release_box],
}
post_actions_by_transition = {}

The resulting schedule is:

DictionaryTransitionActionEffect
preapproachbackground_open_gripper.startstart opening in the background
pregraspbackground_open_gripper.waitwait until opening has finished
pregraspgrasp_boxattach the box and close fingers
prereleaserelease_boxopen fingers and detach the box

Conceptually, execution still has three phases:

#PhaseWhat the arm doesAction before phase
0approachmove above the box, descendstart opening
1transportcarry the box to the goalwait, attach, close
2retreatlift and returnopen and detach

background_open_gripper.start() returns immediately, so the arm can begin the approach while the gripper controller opens the fingers. The later background_open_gripper.wait() blocks before the grasp transition, and grasp_box() runs after that segment so the fingers close once the arm has reached the object. If a dictionary key does not match any segment transition, execute_segments returns False before running any action or trajectory.

Executing the segments

Send the arm segments to the arm controller and let the segment actions command the gripper controller:

from hpp_exec import execute_segments

close_gripper()
reset_box_pose()
execute_segments(
    segments, configs, times,
    joint_names=[f"fr3_joint{i}" for i in range(1, 8)],
    joint_indices=list(range(7)),
    pre_actions_by_transition=pre_actions_by_transition,
    post_actions_by_transition=post_actions_by_transition,
)

close_gripper() is only a setup step to make the overlapping opening visible in Gazebo. During execution you should see the fingers open while the arm starts the approach, then the plan waits before grasping, closes on the box, carries it to the goal, opens again, and retreats.

reset_box_pose() detaches the simulated box if needed and places it back at the planned start pose before execution.

HPP-core

Building Status Pipeline status Coverage report Code style: black pre-commit.ci status

This package implements path planning algorithms for kinematic chains. Kinematic chains are represented by class hpp::pinocchio::Device.

The main classes are:

* hpp::core::Problem: defines a canonical path planning problem,
* hpp::core::PathPlanner: implements an algorithm to solve a problem,
* hpp::core::Roadmap: stores a network of collision-free paths
* hpp::core::SteeringMethod: builds paths between configurations taking into
  account kinematic constraints.
* hpp::core::Path: paths for a robot.

Embedding hpp-core into an application

Class hpp::core::ProblemSolver is a container aiming at embedding hpp-core into an application. It stores elements of the problem that can be provided in random order and builds a valid problem upon call of method solve. After completion of method solve, it stores solution paths.

hpp-manipulation

Building Status Pipeline status Coverage report Code style: black pre-commit.ci status

This package is part of the HPP software and extends the functionalities of hpp-core. It implements a solver for manipulation planning problems.

Dependencies

[hpp-manipulation] needs the following package to be installed:

Installation

Make sure you have installed all the dependency.

$ git clone https://github.com/humanoid-path-planner/hpp-manipulation
$ cd hpp-manipulation
$ mkdir build && cd build
$ cmake ..
$ make install

Todo’s

  • Online modification of the transition probabilities.
  • Solver based on Probabilistic RoadMap.

HPP Constraints

Pipeline status Coverage report Code style: black pre-commit.ci status

Definition of basic geometric constraints for motion planning

  • position, orientation of a frame,

hpp-pinocchio

Building Status Pipeline status Coverage report Code style: black pre-commit.ci status

This package implements a library that wraps the Pinocchio library to be used in the Humanoid Path Planner framework.

Setup

The easiest way to install this package is to uses the installation instructions of HPP. For a manual installation, follow these steps.

To compile this package, it is recommended to create a separate build directory:

mkdir _build
cd _build
cmake [OPTIONS] ..
make install

Please note that CMake produces a CMakeCache.txt file which should be deleted to reconfigure a package from scratch.

Dependencies

The package depends on several packages which have to be available on your machine.

  • Libraries:
    • Boost (>=1.48.0) Boost Test is used in the test suite
    • Pinochio (>=1.1)
  • System tools:
    • CMake (>=2.6)
    • pkg-config
    • usual compilation tools (GCC/G++, make, etc.)

hpp-python package

Provide Python bindings of the HPP software. These bindings differ from the one provided by hpp-corbaserver. They are native bindings that do not use a middleware. The bindings are generated by boost::python.

Compilation

Installation follows the standard CMake procedure:

git clone --recursive ...
mkdir hpp-python/build
cd hpp-python/build
cmake -DCMAKE_INSTALL_PREFIX=... -DCMAKE_BUILD_TYPE=Release ..
make
make test
make install

Generate documentation

Script doc/configure.py is used to generate documentation of Python objects from C++ objects. It reads the XML documentation generated by doxygen so the dependencies must provide such files. To make it work, do:

  • Add GENERATE_XML=YES into doc/Doxyfile.extra.in of all the dependency of this project.
  • Install the generated documentation by adding the following lines to CMakeLists.txt:
IF(_INSTALL_DOC)
  INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/doxygen-xml
    DESTINATION ${CMAKE_INSTALL_DOCDIR})
ENDIF()

File doc/configure.py contains a short documentation of how to document the bindings.

TODO

  • Use doxygen to generate XML documentation of the headers included by a file. Then use the generated XML doc to update the documentation of the files in src/pyhpp. Doxygen configuration variables INCLUDE_PATH and SEARCH_INCLUDES might be helpful.

pyhpp API Reference

Python bindings for HPP — auto-generated from .pyi stubs.

ModuleDescription
pyhpp.corePath planning problem, planners, optimizers, roadmap, steering methods.
pyhpp.core.pathConcrete path types: StraightPath, PathVector, splines.
pyhpp.core.path_optimizationConcrete path optimizer implementations.
pyhpp.core.problem_targetProblem target types (goal configurations, etc.).
pyhpp.constraintsDifferentiable functions, implicit/explicit constraints, hierarchical solver.
pyhpp.manipulationManipulation-specific Device, constraint graph, path planners.
pyhpp.manipulation.urdfURDF/SRDF loading for manipulation devices.
pyhpp.manipulation.steering_methodManipulation-specific steering methods.
pyhpp.pinocchioRobot model (Device), Lie-group utilities.
pyhpp.pinocchio.urdfURDF/SRDF loading for pinocchio devices.

pyhpp.core

Functions

defDescription
def DiscretizedCollision(robot: object, stepSize: float) -> DiscretizedCreate a discretized collision-checking path validation.
def DiscretizedCollisionAndJointBound(robot: object, stepSize: float) -> DiscretizedCreate a discretized path validation checking both collision and joint bounds.
def DiscretizedJointBound(robot: object, stepSize: float) -> DiscretizedCreate a discretized joint-bound path validation.
def NoneProjector(distance: Distance, steeringMethod: SteeringMethod, step: float) -> PathProjectorReturn a null path projector (no projection).
def create(arg1: float, arg2: pyhpp.core.path.bindings.SplineB3) -> PathWrap
def getVerbosityLevel() -> int
def setVerbosityLevel(arg1: pyhpp.core.path.bindings.SplineB3) -> None

BiRRTPlanner

Inherits: PathPlanner

defDescription
def init(self, arg2: Problem) -> None

BiRrtStar

Inherits: PathPlanner

defDescription
def init(self, arg2: Problem) -> None

CollisionPathValidationReport

Inherits: CollisionValidationReport

hpp::core::CollisionPathValidationReport

defDescription
def str(self) -> str

CollisionValidationReport

Inherits: ValidationReport

hpp::core::CollisionValidationReport

defDescription
@property
def object1(self) -> object
@property
def object2(self) -> object
@property
def result(self) -> coal.coal_pywrap.CollisionResult

ConfigProjector

Inherits: Constraint

Implicit non-linear constraint

This class defines a numerical constraints on a robot configuration of the form:

Functions are differentiable functions. Vectors are called right hand side.

The constraints are solved numerically by a Newton Raphson like method.

Numerical constraints can be added using method ConfigProjector::add. Default parameter of this method define equality constraints, but inequality constraints can also be defined by passing an object of type ComparisonType to method.

defDescription
def init(self, arg2: object, arg3: str, arg4: float, arg5: int) -> object
def add(self, numericalConstraint: pyhpp.constraints.bindings.Implicit, priority: int) -> boolnumericalConstraint — The numerical constraint. priority — priority of the function. The last level might be optional.
@typing.overload
def errorThreshold(self, arg2: float) -> None

@typing.overload
def errorThreshold(self) -> float
Set error threshold.
@typing.overload
def lastIsOptional(self) -> bool

@typing.overload
def lastIsOptional(self, arg2: bool) -> None
Get whether the last priority level is treated as optional.
@typing.overload
def maxIterations(self) -> int

@typing.overload
def maxIterations(self, arg2: int) -> None
Get maximal number of iterations in config projector.
def numericalConstraints(self) -> listReturn the list of numerical constraints held by this projector.
def residualError(self) -> float
def setRightHandSideFromConfig(self, arg2: numpy.ndarray) -> NoneSet right-hand side of all constraints from a configuration.
def setRightHandSideOfConstraint(self, arg2: pyhpp.constraints.bindings.Implicit, arg3: numpy.ndarray) -> NoneSet right-hand side of a specific constraint from a configuration.
def sigma(self) -> float
def solver(self) -> pyhpp.constraints.bindings.BySubstitution
@property
def lineSearchType(*args, **kwargs)

@lineSearchType.setter
def lineSearchType(*args, **kwargs)
Get/set the line search type.

ConfigValidation

Abstraction of configuration validation

Instances of this class validate configurations with respect to some criteria

defDescription
@typing.overload
def validate(self, config: numpy.ndarray, validationReport: ValidationReport) -> bool

@typing.overload
def validate(self, arg2: numpy.ndarray) -> tuple
config — the config to check for validity, validationReport — report on validation. If non valid, a validation report will be allocated and returned via this shared pointer.

ConfigValidations

Inherits: ConfigValidation

Validate a configuration with respect to collision

defDescription
def add(self, configValidation: ConfigValidation) -> NoneAdd a configuration validation object.
def clear(self) -> NoneRemove all config validations.
def numberConfigValidations(self) -> intReturn the number of config validations.

ConfigurationShooter

Abstraction of configuration shooter

Configuration shooters are used by random sampling algorithms to generate new configurations

defDescription
def shoot(self) -> numpy.ndarrayShoot a random configuration.

ConnectedComponent

Connected component

Set of nodes reachable from one another.

defDescription
def eq(self, arg2: ConnectedComponent) -> boolReturn true if both objects refer to the same connected component.
def nodes(self) -> listAccess to the nodes.
def reachableFrom(self) -> list
def reachableTo(self) -> list

Constraint

Constraint applicable to a robot configuration

Constraint::apply takes as input a configuration and changes it into a configuration satisfying the constraint.

User should define impl_compute in derived classes.

defDescription
def str(self) -> str
def apply(self, arg2: numpy.ndarray) -> boolApply constraint to q in-place. Returns true on success.
def copy(self) -> ConstraintReturn a copy of this constraint.
@typing.overload
def isSatisfied(self, arg2: numpy.ndarray) -> bool

@typing.overload
def isSatisfied(self, arg2: numpy.ndarray, arg3: numpy.ndarray) -> bool
Return true if configuration q satisfies the constraint.
def name(self) -> objectGet name of constraint.

ConstraintSet

Inherits: Constraint

Set of constraints applicable to a robot configuration

If the set is to contain a ConfigProjector and several LockedJoint instances, the configProjector should be inserted first since following numerical projections might affect locked degrees of freedom.

defDescription
def init(self, arg2: object, arg3: str) -> object
def addConstraint(self, constraint: Constraint) -> NoneAdd a constraint to the set.
def configProjector(self) -> ConfigProjectorReturn pointer to config projector if any.

Dichotomy

Inherits: PathValidation

Abstraction of path validation

Instances of this class compute the latest valid configuration along a path.

Method validate(ConfigurationIn_tq)

is provided to validate single configurations. It is particularly useful to test the initial and goal configurations of a path planning problem using this path validation.

defDescription
def init(self, robot: object, tolerance: float) -> objectCreate a dichotomy-based continuous path validation.

DichotomyProjector

Inherits: PathProjector

This class projects a path using constraints.

defDescription
def init(self, distance: Distance, steeringMethod: SteeringMethod, step: float) -> objectCreate a dichotomy-based path projector with the given step size.

DiffusingPlanner

Inherits: PathPlanner

defDescription
def init(self, arg2: Problem) -> None

Discretized

Inherits: PathValidation

Abstraction of path validation

Instances of this class compute the latest valid configuration along a path.

Method validate(ConfigurationIn_tq)

is provided to validate single configurations. It is particularly useful to test the initial and goal configurations of a path planning problem using this path validation.

defDescription
def init(self, robot: object, stepSize: float) -> objectCreate a discretized collision-checking path validation.

Distance

Abstract class for distance between configurations.

defDescription
@staticmethod
def compute(self_: WeighedDistance, q1: numpy.ndarray, q2: numpy.ndarray) -> float

Dubins

Inherits: SteeringMethod

defDescription
def init(self, arg2: Problem) -> None

GlobalProjector

Inherits: PathProjector

This class projects a path using constraints.

defDescription
def init(self, distance: Distance, steeringMethod: SteeringMethod, step: float) -> objectCreate a global path projector with the given step size.

Hermite

Inherits: SteeringMethod

defDescription
def init(self, arg2: Problem) -> None

JointBoundValidationReport

Inherits: ValidationReport

report returned when a configuration is not within the bounds

defDescription
@property
def joint_(self) -> object
@property
def lowerBound_(self) -> float
@property
def rank_(self) -> int
@property
def upperBound_(self) -> float
@property
def value_(self) -> float

Kinodynamic

Inherits: SteeringMethod

defDescription
def init(self, arg2: Problem) -> None

LineSearchType

Inherits: int


Node

Node of a roadmap

Stores a configuration.

defDescription
@typing.overload
def init(self, arg2: numpy.ndarray) -> None

@typing.overload
def init(self, arg2: numpy.ndarray, arg3: ConnectedComponent) -> None
def addInEdge(self, edge: object) -> None
def addOutEdge(self, edge: object) -> None
def configuration(self) -> object
@typing.overload
def connectedComponent(self) -> ConnectedComponent

@typing.overload
def connectedComponent(self, arg2: ConnectedComponent) -> None
Return the connected component the node belongs to.
def inEdges(self) -> objectAccess to inEdges.
def isInNeighbor(self, n: Node) -> bool
def isOutNeighbor(self, n: Node) -> bool
def outEdges(self) -> objectAccess to outEdges.

Parameter

defDescription
def init(self) -> Parameter
def boolValue(self) -> boolReturn the boolean value of this parameter.
@staticmethod
def create_bool(arg1: bool) -> Parameter
Create a Parameter holding a boolean value.
def floatValue(self) -> floatReturn the floating-point value of this parameter.
def intValue(self) -> intReturn the integer value of this parameter.
def matrixValue(self) -> numpy.ndarrayReturn the matrix value of this parameter.
def stringValue(self) -> strReturn the string value of this parameter.
def value(self) -> objectReturn the parameter value as a Python object (bool, int, float, str, numpy array).
def vectorValue(self) -> numpy.ndarrayReturn the vector value of this parameter.

PartialShortcut

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object

Path

Abstraction of paths: mapping from time to configuration space

A path is defined by:

where

is given by timeRange

is the child class implementation of impl_compute

constraints.apply corresponds to calling Constraint::apply to constraints

Optionally, it is possible to time-parameterize the path with a function . By default, is the identity. The model becomes:

where is the timeParameterization, from timeRange to paramRange.

defDescription
@typing.overload
def call(self, arg2: float) -> tuple

@typing.overload
def call(self, arg2: numpy.ndarray, arg3: float) -> bool
Evaluate path at parameter t. Returns (configuration, success).
def str(self) -> str
def constraints(self) -> ConstraintSetReturn the constraint set attached to the path, or None.
def copy(self) -> PathReturn a shared pointer to a copy of this.
def derivative(self, arg2: float, arg3: int) -> numpy.ndarrayCompute derivative of given order at parameter t. Returns a numpy vector.
def end(self) -> numpy.ndarrayGet the final configuration.
@typing.overload
def eval(self, arg2: float) -> tuple

@typing.overload
def eval(self, arg2: numpy.ndarray, arg3: float) -> bool
Evaluate path at parameter t. Returns (configuration, success).
@typing.overload
def extract(self, self_: float, subInterval: float) -> Path

@typing.overload
def extract(self, arg2: interval) -> Path
subInterval — interval of definition of the extract path If upper bound of subInterval is smaller than lower bound, result is reversed. :param :is thrown when an end configuration of the returned path could not be computed due to projection failure.
def initial(self) -> numpy.ndarrayGet the initial configuration.
def length(self) -> floatGet length of definition interval.
def outputDerivativeSize(self) -> intGet size of velocity.
def outputSize(self) -> intGet size of configuration space.
def paramRange(self) -> interval
def reverse(self) -> Path
def timeRange(self) -> intervalGet interval of definition.

PathOptimizer

Abstraction of path optimizer

defDescription
def interrupt(self) -> NoneInterrupt path optimization.
def maxIterations(self, n: int) -> NoneSet maximal number of iterations.
def optimize(self, path: pyhpp.core.path.bindings.Vector) -> pyhpp.core.path.bindings.VectorOptimize path.
def problem(self) -> CppCoreProblemGet problem.
def timeOut(self, timeOut: float) -> Noneset time out (in seconds)

PathPlanner

Path planner

Algorithm that computes a path between an initial configuration and a set of goal configurations.

defDescription
def computePath(self) -> pyhpp.core.path.bindings.VectorFind a path in the roadmap and transform it in trajectory.
def finishSolve(self, path: pyhpp.core.path.bindings.Vector) -> pyhpp.core.path.bindings.VectorPost processing of the resulting path.
def interrupt(self) -> NoneInterrupt path planning.
@typing.overload
def maxIterations(self) -> int

@typing.overload
def maxIterations(self, arg2: int) -> None
Get maximal number of iterations.
def oneStep(self) -> NoneUser implementation of one step of resolution.
def problem(self) -> CppCoreProblemGet problem.
def roadmap(self) -> RoadmapGet roadmap.
def solve(self) -> pyhpp.core.path.bindings.Vector
def startSolve(self) -> None
def stopWhenProblemIsSolved(self, enable: bool) -> None
@typing.overload
def timeOut(self) -> float

@typing.overload
def timeOut(self, arg2: float) -> None
Get time out.
def tryConnectInitAndGoals(self) -> NoneTry to connect initial and goal configurations to existing roadmap.

PathProjector

This class projects a path using constraints.

defDescription
@typing.overload
def apply(self, path: Path, projection: Path) -> bool

@typing.overload
def apply(self, arg2: Path) -> tuple
the — input path, the — output path.

PathValidation

Abstraction of path validation

Instances of this class compute the latest valid configuration along a path.

Method validate(ConfigurationIn_tq)

is provided to validate single configurations. It is particularly useful to test the initial and goal configurations of a path planning problem using this path validation.

defDescription
@typing.overload
def validate(self, path: Path, reverse: bool, validPart: Path, report: PathValidationReport) -> bool

@typing.overload
def validate(self, arg2: Path, arg3: bool) -> tuple
:param :the path to check for validity, reverse — if true check from the end, the — extracted valid part of the path, pointer to path if path is valid. report — information about the validation process. A report is allocated if the path is not valid.
def validateConfiguration(self, arg2: numpy.ndarray) -> tupleValidate a configuration; returns (valid, report).

PathValidationReport

Inherits: ValidationReport

hpp::core::PathValidationReport

defDescription
@property
def configurationReport(self) -> pyhpp.core.bindings.ValidationReport

@configurationReport.setter
def configurationReport(self, arg2: pyhpp.core.bindings.ValidationReport) -> None
@property
def parameter(self) -> float

@parameter.setter
def parameter(self, arg2: float) -> None

PathWrap

Inherits: Path

defDescription
def init(self, arg2: interval, arg3: int, arg4: int) -> None
@typing.overload
def copy(self) -> Path

@typing.overload
def copy(self) -> None
@typing.overload
def copy_constrained(self, arg2: ConstraintSet) -> Path

@typing.overload
def copy_constrained(self, arg2: ConstraintSet) -> None
@typing.overload
def end(self) -> numpy.ndarray

@typing.overload
def end(self) -> None
@typing.overload
def impl_compute(self, arg2: numpy.ndarray, arg3: float) -> bool

@typing.overload
def impl_compute(self, arg2: numpy.ndarray, arg3: float) -> None
@typing.overload
def impl_derivative(self, arg2: numpy.ndarray, arg3: float, arg4: int) -> None

@typing.overload
def impl_derivative(self, arg2: numpy.ndarray, arg3: float, arg4: int) -> None
def initPtr(self, arg2: PathWrap) -> None
@typing.overload
def initial(self) -> numpy.ndarray

@typing.overload
def initial(self) -> None
@typing.overload
def reverse(self) -> Path

@typing.overload
def reverse(self) -> Path

PlanAndOptimize

Inherits: PathPlanner

defDescription
def init(self, arg2: PathPlanner) -> None

Problem

Defines a path planning problem for one robot. A path planning problem is defined by

a robot: instance of class hpp::pinocchio::Device,

a set of obstacles: a list of hpp::pinocchio::CollisionObject,

initial and goal configurations,

a SteeringMethod to handle the robot dynamics, Additional objects are stored in this object:

a method to validate paths,

a set of methods to validate configurations. Default methods are collision checking and joint bound checking.

defDescription
def init(self, arg2: object) -> None
def addConfigValidation(self, configValidation: str) -> NoneAdd a config validation method.
def addGoalConfig(self, config: numpy.ndarray) -> None
@typing.overload
def addNumericalConstraintsToConfigProjector(self, arg2: str, arg3: list, arg4: list) -> None

@typing.overload
def addNumericalConstraintsToConfigProjector(self, arg2: str, arg3: list) -> None
Add constraints with priorities to the config projector, creating it if needed.
def addPartialCom(self, arg2: str, arg3: list) -> NoneCreate a named partial COM computation from a list of joint names.
def applyConstraints(self, arg2: numpy.ndarray) -> tupleProject config onto active constraints. Returns (success, projected_config, residual_error).
def clearConfigValidations(self) -> None
@typing.overload
def configValidation(self) -> ConfigValidations

@typing.overload
def configValidation(self, configValidation: ConfigValidations) -> None
Get the config validations object.
@typing.overload
def configurationShooter(self) -> ConfigurationShooter

@typing.overload
def configurationShooter(self, configurationShooter: ConfigurationShooter) -> None
Get the configuration shooter.
def createComBetweenFeet(self, arg2: str, arg3: str, arg4: str, arg5: str, arg6: numpy.ndarray, arg7: numpy.ndarray, arg8: str, arg9: numpy.ndarray, arg10: list) -> pyhpp.constraints.bindings.ImplicitCreate an implicit constraint: COM lies between two contact points.
def createRelativeComConstraint(self, arg2: str, arg3: str, arg4: str, arg5: numpy.ndarray, arg6: list) -> pyhpp.constraints.bindings.ImplicitCreate an implicit constraint: relative COM equals a reference point expressed in a joint frame.
@typing.overload
def createTransformationConstraint(self, arg2: str, arg3: str, arg4: str, arg5: pinocchio.pinocchio_pywrap_default.SE3, arg6: list) -> pyhpp.constraints.bindings.Implicit

@typing.overload
def createTransformationConstraint(self, arg2: str, arg3: str, arg4: str, arg5: pinocchio.pinocchio_pywrap_default.SE3, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: list) -> pyhpp.constraints.bindings.Implicit
Create a relative or absolute transformation constraint between two frames, with a 6-bool mask.
def directPath(self, arg2: numpy.ndarray, arg3: numpy.ndarray, arg4: bool) -> tupleCompute a direct path using the steering method. Returns (valid, path, report).
@typing.overload
def distance(self) -> Distance

@typing.overload
def distance(self, distance: Distance) -> None
Get the distance function.
def getConstraints(self) -> ConstraintSetReturn the active constraint set.
def getParameter(self, name: str) -> Parametername — of the parameter.
def getPartialCom(self, arg2: str) -> numpy.ndarrayCompute and return the position of the named partial center of mass.
def initConfig(self, self_: numpy.ndarray) -> NoneGet shared pointer to initial configuration.
def isConfigValid(self, arg2: numpy.ndarray) -> tupleValidate config against all config validations. Returns (valid, report).
@typing.overload
def pathProjector(self) -> PathProjector

@typing.overload
def pathProjector(self, pathProjector: PathProjector) -> None
Get the path projector.
@typing.overload
def pathValidation(self) -> PathValidation

@typing.overload
def pathValidation(self, pathValidation: PathValidation) -> None
Get the path validation object.
def resetGoalConfigs(self) -> None
def robot(self) -> objectreturn shared pointer to robot.
def setConstantRightHandSide(self, arg2: pyhpp.constraints.bindings.Implicit, arg3: bool) -> NoneIf constant=True, set comparison type to EqualToZero; otherwise to Equality.
def setConstraints(self, arg2: ConstraintSet) -> NoneSet the active constraint set used by applyConstraints.
@typing.overload
def setParameter(self, name: str, value: Parameter) -> None

@typing.overload
def setParameter(self, arg2: str, arg3: float) -> None

@typing.overload
def setParameter(self, arg2: str, arg3: int) -> None
name — of the parameter. value — value of the parameter std — :invalid_argument:if a parameter exists but has a different type.
def setRightHandSideFromConfig(self, arg2: numpy.ndarray) -> NoneUpdate right-hand side of the config projector from a configuration.
@typing.overload
def steeringMethod(self) -> SteeringMethod

@typing.overload
def steeringMethod(self, arg2: SteeringMethod) -> None
Get the steering method.
@typing.overload
def target(self) -> ProblemTarget

@typing.overload
def target(self, target: ProblemTarget) -> None
Get the problem target.
@property
def errorThreshold(*args, **kwargs)

@errorThreshold.setter
def errorThreshold(*args, **kwargs)
Error threshold used when creating a new ConfigProjector.
@property
def maxIterProjection(*args, **kwargs)

@maxIterProjection.setter
def maxIterProjection(*args, **kwargs)
Maximum iterations for projection used when creating a new ConfigProjector.

ProblemTarget

Problem target

This abstract class defines the goal to be reached by a planning algorithm.


Progressive

Inherits: PathValidation

Abstraction of path validation

Instances of this class compute the latest valid configuration along a path.

Method validate(ConfigurationIn_tq)

is provided to validate single configurations. It is particularly useful to test the initial and goal configurations of a path planning problem using this path validation.

defDescription
def init(self, robot: object, tolerance: float) -> objectCreate a progressive continuous path validation.

ProgressiveProjector

Inherits: PathProjector

This class projects a path using constraints.

defDescription
def init(self, distance: Distance, steeringMethod: SteeringMethod, step: float) -> objectCreate a progressive path projector with the given step size.

RSTimeParameterization

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object

RandomShortcut

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object

RecursiveHermiteProjector

Inherits: PathProjector

This class projects a path using constraints.

defDescription
def init(self, distance: Distance, steeringMethod: SteeringMethod, step: float) -> objectCreate a recursive Hermite path projector with the given step size.

ReedsShepp

Inherits: SteeringMethod

defDescription
def init(self, arg2: Problem) -> None

Roadmap

Roadmap built by random path planning methods Nodes are configurations, paths are collision-free paths.

defDescription
def init(self, arg2: Distance, arg3: object) -> object
def str(self) -> str
@typing.overload
def addEdge(self, arg2: numpy.ndarray, arg3: numpy.ndarray, arg4: Path) -> None

@typing.overload
def addEdge(self, arg2: numpy.ndarray, arg3: numpy.ndarray, arg4: Path, arg5: bool) -> None
Add nodes at from and to, then add a directed edge between them.
def addEdges(self, from_: Node, to: Node, path: Path) -> Nonefrom — first node to — second node :param :path going from
def addGoalNode(self, config: numpy.ndarray) -> Nodeconfig — configuration If configuration is already in the roadmap, tag corresponding node as goal node. Otherwise create a new node.
def addNode(self, arg2: numpy.ndarray) -> NoneAdd a node with the given configuration to the roadmap.
def addNodeAndEdge(self, arg2: numpy.ndarray, arg3: numpy.ndarray, arg4: Path) -> NoneAdd node at ‘to’ and a single directed edge from the node nearest to ‘from’.
def addNodeAndEdges(self, arg2: numpy.ndarray, arg3: numpy.ndarray, arg4: Path) -> NoneAdd node at ‘to’ and edges from the node nearest to ‘from’.
def clear(self) -> NoneClear the roadmap by deleting nodes and edges.
def connectedComponentOfNode(self, arg2: numpy.ndarray) -> ConnectedComponentReturn the connected component of the node nearest to the given configuration.
def connectedComponents(self) -> listReturn list of all connected components.
def distance(self) -> Distance
def getConnectedComponent(self, arg2: pyhpp.core.path.bindings.SplineB3) -> ConnectedComponentReturn connected component by index.
def goalNodes(self) -> object
@typing.overload
def initNode(self, arg2: numpy.ndarray) -> None

@typing.overload
def initNode(self) -> Node
Set the initial node to the given configuration.
def insertPathVector(self, path: pyhpp.core.path.bindings.Vector, backAndForth: bool) -> NonebackAndForth — whether to insert the reverse path as well.
def merge(self, other: Roadmap) -> NoneAdd the nodes and edges of a roadmap into this one.
@staticmethod
def nearestNode(*args, **kwargs)
Find nearest node to configuration (optionally searching in reverse direction). Returns (configuration, minDistance).
@typing.overload
def nearestNodes(self, arg2: numpy.ndarray, arg3: int) -> object

@typing.overload
def nearestNodes(self, arg2: numpy.ndarray, arg3: ConnectedComponent, arg4: int) -> object
Find the k nearest nodes to configuration. Returns a list of nodes.
def nodes(self) -> listReturn list of all node configurations in the roadmap.
def nodesConnectedComponent(self, arg2: pyhpp.core.path.bindings.SplineB3) -> listReturn list of configurations in the connected component identified by connectedComponentId.
def nodesWithinBall(self, configuration: numpy.ndarray, connectedComponent: ConnectedComponent, maxDistance: float) -> object
def numberConnectedComponents(self) -> intReturn the number of connected components.
def pathExists(self) -> boolCheck that a path exists between the initial node and one goal node.
def resetGoalNodes(self) -> None

SearchInRoadmap

Inherits: PathPlanner

defDescription
def init(self, arg2: Problem, arg3: Roadmap) -> None

SimpleShortcut

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object

SimpleTimeParameterization

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object
@property
def maxAcceleration(*args, **kwargs)

@maxAcceleration.setter
def maxAcceleration(*args, **kwargs)
The maximum acceleration for each degree of freedom. Not considered if negative.
@property
def order(*args, **kwargs)

@order.setter
def order(*args, **kwargs)
The desired continuity order (0, 1, or 2).
@property
def safety(*args, **kwargs)

@safety.setter
def safety(*args, **kwargs)
A scaling factor for the velocity bounds.

Snibud

Inherits: SteeringMethod

defDescription
def init(self, arg2: Problem) -> None

SplineBezier3

Inherits: SteeringMethod

defDescription
def init(self, arg2: Problem) -> None

SplineBezier5

Inherits: SteeringMethod

defDescription
def init(self, arg2: Problem) -> None

SplineGradientBased_bezier1

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object
@property
def QPAccuracy(*args, **kwargs)

@QPAccuracy.setter
def QPAccuracy(*args, **kwargs)
Accuracy of the QP solver (only used by proxqp).
@property
def alphaInit(*args, **kwargs)

@alphaInit.setter
def alphaInit(*args, **kwargs)
In [0,1]. Initial value when interpolating between non-colliding current solution and the optimal colliding trajectory.
@property
def alwaysStopAtFirst(*args, **kwargs)

@alwaysStopAtFirst.setter
def alwaysStopAtFirst(*args, **kwargs)
If true, consider only one (not all) collision constraint per iteration.
@property
def checkJointBound(*args, **kwargs)

@checkJointBound.setter
def checkJointBound(*args, **kwargs)
If true, joint bounds are enforced.
@property
def costOrder(*args, **kwargs)

@costOrder.setter
def costOrder(*args, **kwargs)
Order of the derivative used for the optimized cost function (most likely 1, 2, or 3).
@property
def costThreshold(*args, **kwargs)

@costThreshold.setter
def costThreshold(*args, **kwargs)
Stop optimizing if the cost improves less than this threshold between two iterations.
@property
def guessThreshold(*args, **kwargs)

@guessThreshold.setter
def guessThreshold(*args, **kwargs)
Threshold to detect rows of zeros in the Jacobian (passive DoF). Negative disables the check.
@property
def linearizeAtEachStep(*args, **kwargs)

@linearizeAtEachStep.setter
def linearizeAtEachStep(*args, **kwargs)
If true, collision constraint will be re-linearized at each iteration.
@property
def reorderIntervals(*args, **kwargs)

@reorderIntervals.setter
def reorderIntervals(*args, **kwargs)
If true, intervals in collision are checked first at the next iteration.
@property
def returnOptimum(*args, **kwargs)

@returnOptimum.setter
def returnOptimum(*args, **kwargs)
If true, returns the optimum regardless of collision (for debugging).
@property
def usePathLengthAsWeights(*args, **kwargs)

@usePathLengthAsWeights.setter
def usePathLengthAsWeights(*args, **kwargs)
If true, the initial path length is used to weight the splines.

SplineGradientBased_bezier3

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object
@property
def QPAccuracy(*args, **kwargs)

@QPAccuracy.setter
def QPAccuracy(*args, **kwargs)
Accuracy of the QP solver (only used by proxqp).
@property
def alphaInit(*args, **kwargs)

@alphaInit.setter
def alphaInit(*args, **kwargs)
In [0,1]. Initial value when interpolating between non-colliding current solution and the optimal colliding trajectory.
@property
def alwaysStopAtFirst(*args, **kwargs)

@alwaysStopAtFirst.setter
def alwaysStopAtFirst(*args, **kwargs)
If true, consider only one (not all) collision constraint per iteration.
@property
def checkJointBound(*args, **kwargs)

@checkJointBound.setter
def checkJointBound(*args, **kwargs)
If true, joint bounds are enforced.
@property
def costOrder(*args, **kwargs)

@costOrder.setter
def costOrder(*args, **kwargs)
Order of the derivative used for the optimized cost function (most likely 1, 2, or 3).
@property
def costThreshold(*args, **kwargs)

@costThreshold.setter
def costThreshold(*args, **kwargs)
Stop optimizing if the cost improves less than this threshold between two iterations.
@property
def guessThreshold(*args, **kwargs)

@guessThreshold.setter
def guessThreshold(*args, **kwargs)
Threshold to detect rows of zeros in the Jacobian (passive DoF). Negative disables the check.
@property
def linearizeAtEachStep(*args, **kwargs)

@linearizeAtEachStep.setter
def linearizeAtEachStep(*args, **kwargs)
If true, collision constraint will be re-linearized at each iteration.
@property
def reorderIntervals(*args, **kwargs)

@reorderIntervals.setter
def reorderIntervals(*args, **kwargs)
If true, intervals in collision are checked first at the next iteration.
@property
def returnOptimum(*args, **kwargs)

@returnOptimum.setter
def returnOptimum(*args, **kwargs)
If true, returns the optimum regardless of collision (for debugging).
@property
def usePathLengthAsWeights(*args, **kwargs)

@usePathLengthAsWeights.setter
def usePathLengthAsWeights(*args, **kwargs)
If true, the initial path length is used to weight the splines.

SplineGradientBased_bezier5

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object
@property
def QPAccuracy(*args, **kwargs)

@QPAccuracy.setter
def QPAccuracy(*args, **kwargs)
Accuracy of the QP solver (only used by proxqp).
@property
def alphaInit(*args, **kwargs)

@alphaInit.setter
def alphaInit(*args, **kwargs)
In [0,1]. Initial value when interpolating between non-colliding current solution and the optimal colliding trajectory.
@property
def alwaysStopAtFirst(*args, **kwargs)

@alwaysStopAtFirst.setter
def alwaysStopAtFirst(*args, **kwargs)
If true, consider only one (not all) collision constraint per iteration.
@property
def checkJointBound(*args, **kwargs)

@checkJointBound.setter
def checkJointBound(*args, **kwargs)
If true, joint bounds are enforced.
@property
def costOrder(*args, **kwargs)

@costOrder.setter
def costOrder(*args, **kwargs)
Order of the derivative used for the optimized cost function (most likely 1, 2, or 3).
@property
def costThreshold(*args, **kwargs)

@costThreshold.setter
def costThreshold(*args, **kwargs)
Stop optimizing if the cost improves less than this threshold between two iterations.
@property
def guessThreshold(*args, **kwargs)

@guessThreshold.setter
def guessThreshold(*args, **kwargs)
Threshold to detect rows of zeros in the Jacobian (passive DoF). Negative disables the check.
@property
def linearizeAtEachStep(*args, **kwargs)

@linearizeAtEachStep.setter
def linearizeAtEachStep(*args, **kwargs)
If true, collision constraint will be re-linearized at each iteration.
@property
def reorderIntervals(*args, **kwargs)

@reorderIntervals.setter
def reorderIntervals(*args, **kwargs)
If true, intervals in collision are checked first at the next iteration.
@property
def returnOptimum(*args, **kwargs)

@returnOptimum.setter
def returnOptimum(*args, **kwargs)
If true, returns the optimum regardless of collision (for debugging).
@property
def usePathLengthAsWeights(*args, **kwargs)

@usePathLengthAsWeights.setter
def usePathLengthAsWeights(*args, **kwargs)
If true, the initial path length is used to weight the splines.

SteeringMethod

Steering method

A steering method creates paths between pairs of configurations for a robot. They are usually used to take into account nonholonomic constraints of some robots

defDescription
def call(self, arg2: numpy.ndarray, arg3: numpy.ndarray) -> PathCompute a path between two configurations using the steering method.
@typing.overload
def constraints(self, constraints: ConstraintSet) -> None

@typing.overload
def constraints(self) -> ConstraintSet
Set constraint set.
def problem(self) -> CppCoreProblem
def steer(self, q1: numpy.ndarray, q2: numpy.ndarray) -> Path

Straight

Inherits: SteeringMethod

defDescription
def init(self, arg2: Problem) -> None

StraightPath

Inherits: Path

defDescription
@typing.overload
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace, arg3: numpy.ndarray, arg4: numpy.ndarray, arg5: interval, arg6: ConstraintSet) -> object

@typing.overload
def init(self, arg2: object, arg3: numpy.ndarray, arg4: numpy.ndarray, arg5: interval, arg6: ConstraintSet) -> object

TrapezoidalTimeParameterization

Inherits: PathOptimizer

defDescription
def init(self, arg2: object) -> object
@property
def maxAcceleration(*args, **kwargs)

@maxAcceleration.setter
def maxAcceleration(*args, **kwargs)
Maximum acceleration for each output degree of freedom.
@property
def maxVelocity(*args, **kwargs)

@maxVelocity.setter
def maxVelocity(*args, **kwargs)
Maximum velocity for each output degree of freedom.
@property
def minimumDuration(*args, **kwargs)

@minimumDuration.setter
def minimumDuration(*args, **kwargs)
Minimum duration assigned to each non-empty subpath.

ValidationReport

Abstraction of validation report for paths and configurations

This class is aimed at being derived to store information relative to various Validation derived classes

CollisionValidation,

collision related PathValidation classes.

defDescription
def str(self) -> str

VisibilityPrmPlanner

Inherits: PathPlanner

defDescription
def init(self, arg2: Problem) -> None

WeighedDistance

Inherits: Distance

Weighed distance between configurations

Euclidean distance between configurations seen as vectors. Each degree of freedom is weighed by a positive value.

defDescription
def init(self, arg2: object) -> object
def asDistancePtr_t(self) -> DistanceReturn a clone of this WeighedDistance as a Distance shared pointer.
def getWeights(self) -> numpy.ndarrayReturn the weight vector used when computing distances.
def setWeights(self, arg2: numpy.ndarray) -> NoneSet the weight vector used when computing distances.

interval

defDescription
@typing.overload
def init(self) -> None

@typing.overload
def init(self, arg2: float, arg3: float) -> None
@property
def first(self) -> float

@first.setter
def first(self, arg2: float) -> None
@property
def second(self) -> float

@second.setter
def second(self, arg2: float) -> None

kPrmStar

Inherits: PathPlanner

defDescription
def init(self, arg2: Problem) -> None

pyhpp.core.path

SplineB1

Inherits: pyhpp.core.bindings.Path

defDescription
def basisFunctionDerivative(self, arg2: int, arg3: float, arg4: numpy.ndarray) -> None
@typing.overload
def parameterDerivativeCoefficients(self, arg2: float) -> numpy.ndarray

@typing.overload
def parameterDerivativeCoefficients(self, arg2: numpy.ndarray, arg3: float) -> None
def parameterIntegrate(self, arg2: numpy.ndarray) -> None
def parameterSize(self) -> int
def rowParameters(self) -> numpy.ndarray
def squaredNormBasisFunctionIntegral(self, arg2: int, arg3: numpy.ndarray) -> None
def squaredNormIntegral(self, arg2: int) -> float
def squaredNormIntegralDerivative(self, arg2: int, arg3: numpy.ndarray) -> None

SplineB3

Inherits: pyhpp.core.bindings.Path

defDescription
def basisFunctionDerivative(self, arg2: int, arg3: float, arg4: numpy.ndarray) -> None
@typing.overload
def parameterDerivativeCoefficients(self, arg2: float) -> numpy.ndarray

@typing.overload
def parameterDerivativeCoefficients(self, arg2: numpy.ndarray, arg3: float) -> None
def parameterIntegrate(self, arg2: numpy.ndarray) -> None
def parameterSize(self) -> int
def rowParameters(self) -> numpy.ndarray
def squaredNormBasisFunctionIntegral(self, arg2: int, arg3: numpy.ndarray) -> None
def squaredNormIntegral(self, arg2: int) -> float
def squaredNormIntegralDerivative(self, arg2: int, arg3: numpy.ndarray) -> None

Vector

Inherits: pyhpp.core.bindings.Path

defDescription
def init(self, arg2: int, arg3: int) -> objectCreate an empty path vector. param: inputSize dimension of the configuration space, inputDerivativeSize dimension of the tangent space.
def appendPath(self, path: pyhpp.core.bindings.Path) -> NoneAppend a path at the end of the vector.
def concatenate(self, path: Vector) -> None:param :path to append at the end of this one
def flatten(self, flattenedPath: Vector) -> None
def numberPaths(self) -> intGet the number of sub paths.
def pathAtRank(self, rank: int) -> pyhpp.core.bindings.Pathrank — rank of the path in the vector. Should be between 0 and numberPaths ().
def rankAtParam(self, param: float, localParam: float) -> intparam — parameter in interval of definition, localParam — parameter on sub-path

Vectors

defDescription
def contains(self, arg2: object) -> bool
def delitem(self, arg2: object) -> None
def getitem(self, arg2: object) -> object
def init(self) -> None
def iter(self) -> object
def len(self) -> int
def setitem(self, arg2: object, arg3: object) -> None
def append(self, arg2: object) -> None
def extend(self, arg2: object) -> None

pyhpp.core.path_optimization

LinearConstraint

defDescription
def init(self, arg2: int, arg3: int) -> None
def addRows(self, arg2: int) -> None
def computeRank(self) -> None
def computeSolution(self, arg2: numpy.ndarray) -> None
def concatenate(self, arg2: LinearConstraint) -> None
def decompose(self, arg2: bool, arg3: bool) -> bool
def isSatisfied(self, arg2: numpy.ndarray, arg3: float) -> bool
@staticmethod
def reduceConstraint(*args, **kwargs)
@property
def J(self) -> numpy.ndarray

@J.setter
def J(self, arg2: numpy.ndarray) -> None
@property
def PK(self) -> numpy.ndarray
@property
def b(self) -> numpy.ndarray

@b.setter
def b(self, arg2: numpy.ndarray) -> None
@property
def rank(self) -> int
@property
def xSol(self) -> numpy.ndarray
@property
def xStar(self) -> numpy.ndarray

QuadraticProgram

defDescription
@typing.overload
def init(self, arg2: int) -> None

@typing.overload
def init(self, arg2: QuadraticProgram, arg3: LinearConstraint) -> None
def addRows(self, arg2: int) -> None
def computeLLT(self) -> None
def decompose(self) -> None
def reduced(self, arg2: LinearConstraint, arg3: QuadraticProgram) -> None
@typing.overload
def solve(self) -> None

@typing.overload
def solve(self, arg2: LinearConstraint, arg3: LinearConstraint) -> float
@property
def H(self) -> numpy.ndarray

@H.setter
def H(self, arg2: numpy.ndarray) -> None
@property
def activeConstraint(self) -> numpy.ndarray
@property
def activeSetSize(self) -> int
@property
def b(self) -> numpy.ndarray

@b.setter
def b(self, arg2: numpy.ndarray) -> None
@property
def bIsZero(self) -> bool

@bIsZero.setter
def bIsZero(self, arg2: bool) -> None
@property
def dec(self) -> eigenpy.eigenpy_pywrap.ColPivHhJacobiSVD
@property
def llt(self) -> eigenpy.eigenpy_pywrap.LLT
@property
def trace(self) -> float
@property
def xStar(self) -> numpy.ndarray

Report

defDescription
@typing.overload
def init(self) -> None

@typing.overload
def init(self, arg2: pyhpp.core.bindings.PathValidationReport, arg3: int) -> None
@property
def first(self) -> pyhpp.core.bindings.PathValidationReport

@first.setter
def first(self, arg2: pyhpp.core.bindings.PathValidationReport) -> None
@property
def second(self) -> int

@second.setter
def second(self, arg2: int) -> None

Reports

defDescription
def contains(self, arg2: object) -> bool
def delitem(self, arg2: object) -> None
def getitem(self, arg2: object) -> object
def init(self) -> None
def iter(self) -> object
def len(self) -> int
def setitem(self, arg2: object, arg3: object) -> None
def append(self, arg2: object) -> None
def empty(self) -> bool
def extend(self, arg2: object) -> None
def push_back(self, arg2: Report) -> None
def size(self) -> int

SplineGradientBasedAbstractB1

Inherits: pyhpp.core.bindings.PathOptimizer

defDescription
def init(self, arg2: object) -> None
def addContinuityConstraints(self, arg2: SplineGradientBasedAbstractB1.Splines, arg3: int, arg4: SplineGradientBasedAbstractB1.SplineOptimizationDatas, arg5: LinearConstraint) -> None
def appendEquivalentSpline(self, arg2: pyhpp.core.path.bindings.Vector, arg3: SplineGradientBasedAbstractB1.Splines) -> None
def buildPathVector(self, arg2: SplineGradientBasedAbstractB1.Splines) -> pyhpp.core.path.bindings.Vector
@staticmethod
def copy(arg1: SplineGradientBasedAbstractB1.Splines, arg2: SplineGradientBasedAbstractB1.Splines) -> None
def initializePathValidation(self, arg2: SplineGradientBasedAbstractB1.Splines) -> None
@staticmethod
def interpolate(arg1: SplineGradientBasedAbstractB1.Splines, arg2: SplineGradientBasedAbstractB1.Splines, arg3: float, arg4: SplineGradientBasedAbstractB1.Splines) -> None
def jointBoundConstraint(self, arg2: SplineGradientBasedAbstractB1.Splines, arg3: LinearConstraint) -> None
def updateParameters(self, arg2: numpy.ndarray, arg3: SplineGradientBasedAbstractB1.Splines) -> None
def updateSplines(self, arg2: SplineGradientBasedAbstractB1.Splines, arg3: numpy.ndarray) -> None
def validatePath(self, arg2: SplineGradientBasedAbstractB1.Splines, arg3: pinocchio.pinocchio_pywrap_default.StdVec_Index, arg4: bool, arg5: bool) -> Reports

SplineOptimizationData

defDescription
@typing.overload
def init(self) -> None

@typing.overload
def init(self, arg2: int) -> None
@property
def activeParameters(self) -> object

@activeParameters.setter
def activeParameters(self, arg2: object) -> None
@property
def es(self) -> pyhpp.constraints.bindings.ExplicitConstraintSet

@es.setter
def es(self, arg2: pyhpp.constraints.bindings.ExplicitConstraintSet) -> None
@property
def set(self) -> pyhpp.core.bindings.ConstraintSet

@set.setter
def set(self, arg2: pyhpp.core.bindings.ConstraintSet) -> None

SplineOptimizationDatas

defDescription
def getitem(self, arg2: int) -> SplineGradientBasedAbstractB1.SplineOptimizationData
@typing.overload
def init(self, arg2: int) -> None

@typing.overload
def init(self, arg2: int, arg3: SplineGradientBasedAbstractB1.SplineOptimizationData) -> None
def iter(self) -> object
def len(self) -> int
def setitem(self, arg2: int, arg3: SplineGradientBasedAbstractB1.SplineOptimizationData) -> None
def append(self, arg2: SplineGradientBasedAbstractB1.SplineOptimizationData) -> None

Splines

defDescription
def contains(self, arg2: object) -> bool
def delitem(self, arg2: object) -> None
def getitem(self, arg2: object) -> object
def init(self) -> None
def iter(self) -> object
def len(self) -> int
def setitem(self, arg2: object, arg3: object) -> None
def append(self, arg2: object) -> None
def empty(self) -> bool
def extend(self, arg2: object) -> None
def push_back(self, arg2: pyhpp.core.path.bindings.SplineB1) -> None
def size(self) -> int

SplineGradientBasedAbstractB3

Inherits: pyhpp.core.bindings.PathOptimizer

defDescription
def init(self, arg2: object) -> None
def addContinuityConstraints(self, arg2: SplineGradientBasedAbstractB3.Splines, arg3: int, arg4: SplineGradientBasedAbstractB3.SplineOptimizationDatas, arg5: LinearConstraint) -> None
def appendEquivalentSpline(self, arg2: pyhpp.core.path.bindings.Vector, arg3: SplineGradientBasedAbstractB3.Splines) -> None
def buildPathVector(self, arg2: SplineGradientBasedAbstractB3.Splines) -> pyhpp.core.path.bindings.Vector
@staticmethod
def copy(arg1: SplineGradientBasedAbstractB3.Splines, arg2: SplineGradientBasedAbstractB3.Splines) -> None
def initializePathValidation(self, arg2: SplineGradientBasedAbstractB3.Splines) -> None
@staticmethod
def interpolate(arg1: SplineGradientBasedAbstractB3.Splines, arg2: SplineGradientBasedAbstractB3.Splines, arg3: float, arg4: SplineGradientBasedAbstractB3.Splines) -> None
def jointBoundConstraint(self, arg2: SplineGradientBasedAbstractB3.Splines, arg3: LinearConstraint) -> None
def updateParameters(self, arg2: numpy.ndarray, arg3: SplineGradientBasedAbstractB3.Splines) -> None
def updateSplines(self, arg2: SplineGradientBasedAbstractB3.Splines, arg3: numpy.ndarray) -> None
def validatePath(self, arg2: SplineGradientBasedAbstractB3.Splines, arg3: pinocchio.pinocchio_pywrap_default.StdVec_Index, arg4: bool, arg5: bool) -> Reports

SplineOptimizationData

defDescription
@typing.overload
def init(self) -> None

@typing.overload
def init(self, arg2: int) -> None
@property
def activeParameters(self) -> object

@activeParameters.setter
def activeParameters(self, arg2: object) -> None
@property
def es(self) -> pyhpp.constraints.bindings.ExplicitConstraintSet

@es.setter
def es(self, arg2: pyhpp.constraints.bindings.ExplicitConstraintSet) -> None
@property
def set(self) -> pyhpp.core.bindings.ConstraintSet

@set.setter
def set(self, arg2: pyhpp.core.bindings.ConstraintSet) -> None

SplineOptimizationDatas

defDescription
def getitem(self, arg2: int) -> SplineGradientBasedAbstractB3.SplineOptimizationData
@typing.overload
def init(self, arg2: int) -> None

@typing.overload
def init(self, arg2: int, arg3: SplineGradientBasedAbstractB3.SplineOptimizationData) -> None
def iter(self) -> object
def len(self) -> int
def setitem(self, arg2: int, arg3: SplineGradientBasedAbstractB3.SplineOptimizationData) -> None
def append(self, arg2: SplineGradientBasedAbstractB3.SplineOptimizationData) -> None

Splines

defDescription
def contains(self, arg2: object) -> bool
def delitem(self, arg2: object) -> None
def getitem(self, arg2: object) -> object
def init(self) -> None
def iter(self) -> object
def len(self) -> int
def setitem(self, arg2: object, arg3: object) -> None
def append(self, arg2: object) -> None
def empty(self) -> bool
def extend(self, arg2: object) -> None
def push_back(self, arg2: pyhpp.core.path.bindings.SplineB3) -> None
def size(self) -> int

pyhpp.core.problem_target

GoalConfigurations

Inherits: pyhpp.core.bindings.ProblemTarget

defDescription
def init(self, arg2: pyhpp.core.bindings.CppCoreProblem) -> object
def computePath(self, arg2: pyhpp.core.bindings.Roadmap) -> pyhpp.core.path.bindings.Vector
def reached(self, arg2: pyhpp.core.bindings.Roadmap) -> bool

pyhpp.constraints

BySubstitution

Inherits: HierarchicalIterative

Solve a non-linear system equations with explicit and implicit constraints

This solver is defined in paper https://hal.archives-ouvertes.fr/hal-01804774/file/paper.pdf. We give here only a brief description

The unknows (denoted by ) of the system of equations is a Lie group. It is usually a robot configuration space or the Cartesian product of robot configuration spaces.

The solver stores a set of implicit numerical constraints: . These implicit constraints are added using method HierarchicalIterative::add.

The solver also stores explicit numerical constraints (constraints where some configuration variables depend on others) in an instance of class ExplicitConstraintSet. This instance is accessible via method BySubstitution::explicitConstraintSet.

When an explicit constraint is added using method ExplicitConstraintSet::add, this method checks that the explicit constraint is compatible with the previously added ones. If so, the constraint is stored in the explicit constraint set. Otherwise, it has to be added as an implicit constraint.

See Section III of the above mentioned paper for the description of the constraint resolution.

defDescription
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None
def describeError(self, arg2: numpy.ndarray) -> tupleDescribe the constraint error for configuration q. Returns a list of (constraint_name, error_norm) pairs.
def explicitConstraintSet(self) -> ExplicitConstraintSetGet explicit constraint set.
def explicitConstraintSetHasChanged(self) -> NoneShould be called whenever explicit solver is modified.
@typing.overload
def rightHandSide(self, arg2: Implicit, arg3: numpy.ndarray) -> bool

@typing.overload
def rightHandSide(self, arg2: numpy.ndarray) -> None

@typing.overload
def rightHandSide(self) -> numpy.ndarray
Set right hand side of a constraint.
@typing.overload
def rightHandSideFromConfig(self, arg2: numpy.ndarray) -> numpy.ndarray

@typing.overload
def rightHandSideFromConfig(self, arg2: Implicit, arg3: numpy.ndarray) -> bool
Compute right hand side of equality constraints from a configuration.
def solve(self, arg2: numpy.ndarray) -> tupleSolve the constraints from configuration q. Returns (output_config, status).
@property
def errorThreshold(*args, **kwargs)

@errorThreshold.setter
def errorThreshold(*args, **kwargs)
Get error threshold.

ComparisonType

Inherits: int


ComparisonTypes

defDescription
def contains(self, arg2: object) -> bool
def delitem(self, arg2: object) -> None
def getitem(self, arg2: object) -> object
def init(self) -> None
def iter(self) -> object
def len(self) -> int
def setitem(self, arg2: object, arg3: object) -> None
def append(self, arg2: object) -> None
def extend(self, arg2: object) -> None

DifferentiableFunction

Differentiable function from a Lie group, for instance the configuration space of a robot (hpp::pinocchio::Device) to a another Lie group.

Note that the input Lie group is only represented by the sizes of the elements and of the velocities: methods inputSize and inputDerivativeSize

The output space can be accessed by method outputSpace.

The value of the function for a given input can be accessed by method value . The Jacobian of the function for a given input can be accessed by method jacobian .

defDescription
def J(self, arg2: numpy.ndarray) -> numpy.ndarrayCompute Jacobian matrix and return as a numpy array.
def call(self, arg2: numpy.ndarray) -> pyhpp.pinocchio.bindings.LiegroupElementEvaluate the function at a given parameter.
def init(self, arg2: int, arg3: int, arg4: int, arg5: str) -> None
def str(self) -> str
@typing.overload
def impl_compute(self, arg2: pyhpp.pinocchio.bindings.LiegroupElementRef, arg3: numpy.ndarray) -> None

@typing.overload
def impl_compute(self, arg2: pyhpp.pinocchio.bindings.LiegroupElementRef, arg3: numpy.ndarray) -> None
@typing.overload
def impl_jacobian(self, arg2: numpy.ndarray, arg3: numpy.ndarray) -> None

@typing.overload
def impl_jacobian(self, arg2: numpy.ndarray, arg3: numpy.ndarray) -> None
def inputDerivativeSize(self) -> int
def inputSize(self) -> intGet dimension of input vector.
def jacobian(self, jacobian: numpy.ndarray, argument: numpy.ndarray) -> None:param :jacobian will be stored in this argument argument — point at which the jacobian will be computed
@typing.overload
def name(self) -> str

@typing.overload
def name(self) -> str
Get function name.
def outputDerivativeSize(self) -> intGet dimension of output derivative vector.
def outputSize(self) -> intGet dimension of output vector.
def outputSpace(self) -> pyhpp.pinocchio.bindings.LiegroupSpaceGet output space.
def value(self, result: pyhpp.pinocchio.bindings.LiegroupElement, argument: numpy.ndarray) -> None
@property
def ndi(*args, **kwargs)
Get dimension of input derivative vector.
@property
def ndo(*args, **kwargs)
Get dimension of output derivative vector.
@property
def ni(*args, **kwargs)
Get dimension of input vector.
@property
def no(*args, **kwargs)
Get dimension of output vector.

Explicit

Explicit numerical constraint

DefinitionAn explicit numerical constraint is a constraint such that some configuration variables called output are function of the others called input.

Let

be the list of indices corresponding to ordered input configuration variables,

be the list of indices corresponding to ordered output configuration variables,

be the list of indices corresponding to ordered input degrees of freedom,

be the list of indices corresponding to ordered output degrees of freedom.

Recall that degrees of freedom refer to velocity vectors.

Let us notice that is less than the robot configuration size, and is less than the velocity size. Some degrees of freedom may indeed be neither input nor output.

Then the differential function is of the form

It is straightforward that an equality constraint with this function can be solved explicitely:

If function takes values in a Lie group (SO(2), SO(3)), the above “+” between a Lie group element and a tangent vector has to be undestood as the integration of the constant velocity from the Lie group element:

where is a Lie group element and is a tangent vector.

Considered as an Implicit instance, the expression of the Jacobian of the DifferentiableFunction above depends on the output space of function . The rows corresponding to values in a vector space are expressed as follows.

for any index between 0 and the size of velocity vectors, either

is an input degree of freedom: integer, such that ,

is an output degree of freedom: integer, such that , or

neither input nor output. In this case, the corresponding column is equal to 0.

The rows corresponding to values in SO(3) have the following expression.

where

is the rotation matrix corresponding to unit quaternion ,

is the rotation matrix corresponding to the part of the output value of corresponding to SO(3),

is the Jacobian matrix of function that associates to a rotation matrix the vector such that

“Domain ofdefinition” Some explicit constraints might be defined over only a subspace of the input

space. If the input value is not in the definition subspace, the explicit constraint will throw an exception of type FunctionNotDefinedForThisValue.

defDescription
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace, arg3: DifferentiableFunction, arg4: list, arg5: list, arg6: list, arg7: list, arg8: ComparisonTypes) -> objectCreate an explicit constraint mapping output DOF from input DOF.

ExplicitConstraintSet

Set of explicit constraints

This class combines compatible explicit constraints as defined in the following paper published in Robotics Science and System 2018: https://hal.archives-ouvertes.fr/hal-01804774/file/paper.pdf, Section II-B Definition 4.

An explicit constraint on a robot configuration space is defined by

a subset of input indices ,

a subset of output indices ,

a smooth mapping from to , satisfying the following properties:

,

for any , is defined by

Right hand side.

For manipulation planning, it is useful to handle a parameterizable right hand side . The expression above thus becomes

The right hand side may be set using the various methods ExplicitConstraintSet::rightHandSide and ExplicitConstraintSet::rightHandSideFromInput.

For some applications like manipulation planning, an invertible function (of known inverse ) can be specified for each explicit constraint . The above expression then becomes:

To add explicit constraints, use methods ExplicitConstraintSet::add. If the constraint to add is not compatible with the previous one, this method returns -1.

Method ExplicitConstraintSet::solve solves the explicit constraints.

The combination of compatible explicit constraints is an explicit constraint. As such this class can be considered as an explicit constraint.

We will therefore use the following notation

for the set of indices of input variables,

for the set of indices of output variables.

defDescription
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None
def str(self) -> str
def add(self, constraint: Explicit) -> intconstraint — explicit constraint
def errorSize(self) -> int

HierarchicalIterative

Solve a system of non-linear equations on a robot configuration

The non-linear system of equations is built by adding equations with method HierarchicalIterative::add.

Note that a hierarchy between the equations can be provided. In this case, the solver will try to solve the highest priority equations first, and then to solve the lower priority equations. Note that priorities are in decreasing order: 0 has higher priority than 1.

The algorithm used is a Newton-Raphson like algorithm that works as follows: for a single level of priority, let be the system of equations where is a mapping from the robot configuration space to a Lie group space .

Starting from initial guess , the method HierarchicalIterative::solve builds a sequence of configurations as follows:

where

is the Moore-Penrose pseudo-inverse of the system Jacobian,

is a sequence of real numbers depending on the line search strategy. Possible line-search strategies are lineSearch::Constant, lineSearch::Backtracking, lineSearch::FixedSequence, lineSearch::ErrorNormBased. until

the residual is below an error threshold, or

the maximal number of iterations has been reached.

The computation of the direction of descent in the case of multiple level of hierarchy is described in this paper.

The error threshold can be accessed by methods HierarchicalIterative::errorThreshold. The maximal number of iterations can be accessed by methods HierarchicalIterative::maxIterations.

Solving equations one after the other

For some applications, it can be more efficient to solve a set of equations one after the other. In other words, an equation is ignored until the previous one is solved (norm below the threshold). To do so, introduce the equations using method HierarchicalIterative::add with increasing value of priority, and call method HierarchicalIterative::solveLevelByLevel(true). Lie group

The unknowns may take values in a more general set than the configuration space of a robot. This set should be a Cartesian product of Lie groups: hpp::pinocchio::LiegroupSpace.

Saturation

Right hand side and comparison types

Instead of , other constraints can be defined. Several comparison types are available:

Equality, where is a parameterizable right hand side,

EqualToZero,

Superior

Inferior If several constraint are of type equality, the right hand side of the system of equations can be modified by methods HierarchicalIterative::rightHandSideFromInput, HierarchicalIterative::rightHandSide.

Free variables

Some variables can be locked, or computed explicitely. In this case, the iterative resolution will only change the other variables called free variables. methods

freeVariables (const Indices_t& indices) and

freeVariables (const Indices_t& indices).

defDescription
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None
def str(self) -> str
def add(self, constraint: Implicit, priority: int) -> boolconstraint — implicit constraint priority — level of priority of the constraint: priority are in decreasing order: 0 is the highest priority level,
def constraintsForPriority(self, arg2: int) -> listReturn list of constraints at the given priority level.
def dimension(self) -> intReturn total dimension of the active constraints.
def numberStacks(self) -> intReturn the number of priority stacks.
@typing.overload
def rightHandSide(self, arg2: Implicit, arg3: numpy.ndarray) -> bool

@typing.overload
def rightHandSide(self, arg2: numpy.ndarray) -> None

@typing.overload
def rightHandSide(self) -> numpy.ndarray
Set right hand side of a constraint.
@typing.overload
def rightHandSideFromConfig(self, arg2: numpy.ndarray) -> numpy.ndarray

@typing.overload
def rightHandSideFromConfig(self, arg2: Implicit, arg3: numpy.ndarray) -> bool
Compute right hand side of equality constraints from a configuration.
@property
def errorThreshold(self) -> float

@errorThreshold.setter
def errorThreshold(self, arg2: float) -> None
@property
def lastIsOptional(*args, **kwargs)

@lastIsOptional.setter
def lastIsOptional(*args, **kwargs)
Whether the last priority level is treated as optional.
@property
def maxIterations(*args, **kwargs)

@maxIterations.setter
def maxIterations(*args, **kwargs)
Get maximal number of iterations in config projector.
@property
def solveLevelByLevel(*args, **kwargs)

@solveLevelByLevel.setter
def solveLevelByLevel(*args, **kwargs)
Whether to solve constraints one priority level at a time.

Implicit

This class represents a parameterizable numerical constraint that compares the output of a function to a right hand side Lie group element.

Definition

The function takes input in a configuration space and output in a Lie group ,

the dimensions of and of its tangent space are respectively .

The comparison is represented by a vector of dimension with values in enum hpp::constraints::ComparisonType = { , , , }.

The right hand side is Lie group element of dimension .

Error

A configuration is said to satisfy the constraint for a given right hand side if and only if the error as computed below is smaller in norm than a given threshold.

Let

for each component ,

if is , ,

if is , ,

if is , ,

if is , .

Mask

A mask is a vector of Boolean values of size . Values set to false means that the corresponding component of the error defined above is not taken into account to determine whether the constraint is satisfied. The active rows of the constraint may be accessed via method activeRows.

Parameterizable right hand side

Lines with comparator in the above definition of the error need a parameter, while lines with comparators , , or do not. As a consequence, the right hand side of the constraint is defined by a vector of parameters of size the number of occurences in vector . The right hand side is then defined as in the following example:

To retrieve the size of vector , call method Implicit::parameterSize (). To set and get the right hand side value, use method Implicit::rightHandSide.

Time varying right hand side

The right hand side of the constraint may depend on time, for instance if the constraint is associated to a trajectory following task. In this case, the right hand side is a function from to .

defDescription
def init(self, arg2: DifferentiableFunction, arg3: ComparisonTypes, arg4: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectCreate an implicit constraint from a differentiable function and comparison types.
@typing.overload
def comparisonType(self) -> ComparisonTypes

@typing.overload
def comparisonType(self, arg2: ComparisonTypes) -> None
Return the ComparisonType.
def function(self) -> DifferentiableFunctionReturn a reference to function .
def getFunctionOutputSize(self) -> intReturn the output size of the underlying differentiable function.
def parameterSize(self) -> int
def rightHandSideSize(self) -> int

LockedJoint

Inherits: Implicit

Implementation of constraint specific to a locked joint.

The implicit formulation as defined in class Implicit is given by

where is an element of the configuration space of the locked joint passed to method create.

Note that takes values in where is the dimension of the joint tangent space.

The explicit formulation is given by

where coordinates of corresponding to comparison types different from Equality are set to 0.

As such, the relation between the explicit formulation and the implicit formulation is the default one.

defDescription
@typing.overload
def init(self, arg2: object, arg3: str, arg4: numpy.ndarray) -> object

@typing.overload
def init(self, arg2: object, arg3: str, arg4: numpy.ndarray, arg5: ComparisonTypes) -> object
Create a locked joint constraint fixing the named joint to the given configuration.

Manipulability

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: DifferentiableFunction, arg3: object, arg4: str) -> objectCreate a manipulability function for the given robot.
def lockJoint(self, arg2: str) -> NoneLock a joint by name so it is excluded from the Jacobian.

MinManipulability

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: DifferentiableFunction, arg3: object, arg4: str) -> objectCreate a minimum-manipulability function for the given robot.
def lockJoint(self, arg2: str) -> NoneLock a joint by name so it is excluded from the Jacobian.

Orientation

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: str, arg3: object, arg4: int, arg5: pinocchio.pinocchio_pywrap_default.SE3, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectname — name of the constraint, robot — device the constraint applies to, j2 — index of joint that holds frame 2, frame2 (SE3): pose of frame 2 in joint 2, frame1 (SE3): pose of frame 1 in world frame, mask — tuple of Boolean.

Position

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: str, arg3: object, arg4: int, arg5: pinocchio.pinocchio_pywrap_default.SE3, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectname — name of the constraint, robot — device the constraint applies to, j2 — index of joint that holds frame 2, frame2 (SE3): pose of frame 2 in joint 2, frame1 (SE3): pose of frame 1 in world frame, mask — tuple of Boolean.

RelativeCom

Inherits: DifferentiableFunction

Constraint on the relative position of the center of mass

The value of the function is defined as the position of the center of mass in the reference frame of a joint.

where

is the position of the joint,

is the position of the center of mass,

is the desired position of the center of mass expressed in joint frame.

defDescription
@typing.overload
def init(self, robot: object, joint: object, reference: numpy.ndarray, mask: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> RelativeCom

@typing.overload
def init(self, arg2: object, arg3: object, arg4: numpy.ndarray, arg5: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> RelativeCom

@typing.overload
def init(self, arg2: object, arg3: object, arg4: object, arg5: numpy.ndarray, arg6: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> RelativeCom
Return a shared pointer to a new instance.

RelativeOrientation

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: str, arg3: object, arg4: int, arg5: int, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.SE3, arg8: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectname — name of the constraint, robot — device the constraint applies to, j1 — index of joint that holds frame 1, j2 — index of joint that holds frame 2, frame1 (SE3): pose of frame 1 in joint 1, frame2 (SE3): pose of frame 2 in joint 2, mask — tuple of Boolean.

RelativePosition

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: str, arg3: object, arg4: int, arg5: int, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.SE3, arg8: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectname — name of the constraint, robot — device the constraint applies to, j1 — index of joint that holds frame 1, j2 — index of joint that holds frame 2, frame1 (SE3): pose of frame 1 in joint 1, frame2 (SE3): pose of frame 2 in joint 2, mask — tuple of Boolean.

RelativeTransformation

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: str, arg3: object, arg4: int, arg5: int, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.SE3, arg8: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectname — name of the constraint, robot — device the constraint applies to, j1 — index of joint that holds frame 1, j2 — index of joint that holds frame 2, frame1 (SE3): pose of frame 1 in joint 1, frame2 (SE3): pose of frame 2 in joint 2, mask — tuple of Boolean.

RelativeTransformationR3xSO3

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: str, arg3: object, arg4: int, arg5: int, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.SE3, arg8: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectname — name of the constraint, robot — device the constraint applies to, j1 — index of joint that holds frame 1, j2 — index of joint that holds frame 2, frame1 (SE3): pose of frame 1 in joint 1, frame2 (SE3): pose of frame 2 in joint 2, mask — tuple of Boolean.

SolverStatus

Inherits: int


Transformation

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: str, arg3: object, arg4: int, arg5: pinocchio.pinocchio_pywrap_default.SE3, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectname — name of the constraint, robot — device the constraint applies to, j2 — index of joint that holds frame 2, frame2 (SE3): pose of frame 2 in joint 2, frame1 (SE3): pose of frame 1 in world frame, mask — tuple of Boolean.

segment

defDescription
@typing.overload
def init(self) -> None

@typing.overload
def init(self, arg2: int, arg3: int) -> None
@property
def first(self) -> int

@first.setter
def first(self, arg2: int) -> None
@property
def second(self) -> int

@second.setter
def second(self, arg2: int) -> None

pyhpp.manipulation

Functions

defDescription
@typing.overload
def DichotomyProjector(distance: pyhpp.core.bindings.Distance, steeringMethod: pyhpp.core.bindings.SteeringMethod, step: float) -> pyhpp.core.bindings.DichotomyProjector

@typing.overload
def DichotomyProjector(distance: pyhpp.core.bindings.Distance, steeringMethod: GraphSteeringMethod, step: float) -> pyhpp.core.bindings.DichotomyProjector
@typing.overload
def GlobalProjector(distance: pyhpp.core.bindings.Distance, steeringMethod: pyhpp.core.bindings.SteeringMethod, step: float) -> pyhpp.core.bindings.GlobalProjector

@typing.overload
def GlobalProjector(distance: pyhpp.core.bindings.Distance, steeringMethod: GraphSteeringMethod, step: float) -> pyhpp.core.bindings.GlobalProjector
def GraphPartialShortcut(arg1: object) -> pyhpp.core.bindings.PathOptimizer
def GraphRandomShortcut(arg1: object) -> pyhpp.core.bindings.PathOptimizer
def NoneProjector() -> pyhpp.core.bindings.PathProjector
@typing.overload
def ProgressiveProjector(distance: pyhpp.core.bindings.Distance, steeringMethod: pyhpp.core.bindings.SteeringMethod, step: float) -> pyhpp.core.bindings.ProgressiveProjector

@typing.overload
def ProgressiveProjector(distance: pyhpp.core.bindings.Distance, steeringMethod: GraphSteeringMethod, step: float) -> pyhpp.core.bindings.ProgressiveProjector
@typing.overload
def RecursiveHermiteProjector(distance: pyhpp.core.bindings.Distance, steeringMethod: pyhpp.core.bindings.SteeringMethod, step: float) -> pyhpp.core.bindings.RecursiveHermiteProjector

@typing.overload
def RecursiveHermiteProjector(distance: pyhpp.core.bindings.Distance, steeringMethod: GraphSteeringMethod, step: float) -> pyhpp.core.bindings.RecursiveHermiteProjector

Device

Inherits: pyhpp.pinocchio.bindings.Device

Device with handles.

As a deriving class of hpp::pinocchio::HumanoidRobot, it is compatible with hpp::pinocchio::urdf::loadHumanoidRobot

This class also contains pinocchio::Gripper, Handle and JointAndShapes_t

defDescription
def init(self, arg2: str) -> None
def addGripper(self, arg2: str, arg3: str, arg4: pinocchio.pinocchio_pywrap_default.SE3, arg5: float) -> NoneAdd a gripper to the kinematic chain
def addHandle(self, arg2: str, arg3: str, arg4: pinocchio.pinocchio_pywrap_default.SE3, arg5: float, arg6: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> NoneAdd a handle to the kinematic chain
@staticmethod
def asPinDevice(arg1: object) -> object
def contactSurfaceNames(self) -> listReturn list of contact surface names registered on device
def contactSurfaces(self) -> dictReturn dict mapping surface names to list of {joint, points}
def getJointConfig(self, arg2: str) -> listReturn current configuration values of the named joint.
def getJointNames(self) -> listReturn list of all joint names in the Pinocchio model.
def grippers(self) -> pyhpp.pinocchio.bindings.GripperMapReturn a map from gripper name to Gripper object.
def handles(self) -> HandleMapReturn a map from handle name to Handle object.
def modelsInfo(self) -> modelsInfoVecReturn list of modelsInfo stored in the device, each element contains the urdf path, srdf path, prefix and initial pose of a model loaded in the device
def setJointBounds(self, arg2: str, arg3: list) -> NoneSet joint bounds from a flat list [min0, max0, min1, max1, …].
def setRobotRootPosition(self, arg2: str, arg3: pinocchio.pinocchio_pywrap_default.SE3) -> NoneSet the root position of a sub-robot (identified by name) relative to its parent joint.

EndEffectorTrajectory

Inherits: pyhpp.core.bindings.PathPlanner

Plan a path for a robot with constrained trajectory of an end effector

This path planner only works with a steering method of type steeringMethod::EndEffectorTrajectory. The steering method defines the desired end-effector trajectory using a time-varying constraint.

To plan a path between two configurations q_init and q_goal, the configurations must satisfy the constraint at the beginning and at the end of the definition interval respectively.

The interval of definition of the output path is defined by the time-varying constraint of the steering method. This interval is uniformly discretized in a number of samples that can be accessed using method nDiscreteSteps .

The path is planned by successively calling method oneStep that performs the following actions.

A vector of configurations is produced by appending random configurations to q_init. The number of random configurations can be accessed by methods nRandomConfig .

for each configuration in the vector,

the initial configuration of the path is computed by projecting the configuration on the constraint,

the configuration at following samples is computed by projecting the configuration at the previous sample using the time-varying constraint.

In case of failure

in projecting a configuration or

in validating the path for collision, the loop restart with the next random configuration.

Note that continuity is not tested but enforced by projecting the configuration of the previous sample to compute the configuration at a given sample. DeprecatedThis class has been reimplemented and simplified as steeringMethod::Cartesian.

defDescription
@typing.overload
def init(self, arg2: pyhpp.core.bindings.Problem) -> None

@typing.overload
def init(self, arg2: pyhpp.core.bindings.Problem, arg3: pyhpp.core.bindings.Roadmap) -> None
@typing.overload
def checkFeasibilityOnly(self) -> bool

@typing.overload
def checkFeasibilityOnly(self, arg2: bool) -> None
If enabled, only add one solution to the roadmap. Otherwise add all solutions.
@typing.overload
def nDiscreteSteps(self) -> int

@typing.overload
def nDiscreteSteps(self, arg2: pyhpp.core.path.bindings.SplineB3) -> None
Number of steps to generate goal config (successive projections).
@typing.overload
def nRandomConfig(self) -> int

@typing.overload
def nRandomConfig(self, arg2: pyhpp.core.path.bindings.SplineB3) -> None
Get the number of random configurations used to generate the initial config of the final path.

EndEffectorTrajectorySteeringMethod

Inherits: pyhpp.core.bindings.SteeringMethod

defDescription
def init(self, arg2: object) -> None
def setTrajectory(self, arg2: pyhpp.core.bindings.Path, arg3: bool) -> NoneSet the right hand side of the trajectory constraint from a path. param se3Output: set to True if the output of path must be understood as SE3.
def setTrajectoryConstraint(self, arg2: pyhpp.constraints.bindings.Implicit) -> NoneSet the constraint whose right hand side will vary along the trajectory.

EnforceTransitionSemantic

Inherits: pyhpp.core.bindings.PathOptimizer

Recompute the transition relative to each element of the path vector

When executing a sequence of direct paths on a real robot, it is useful to know which

transition of the graph each direct path corresponds to. For example, in a manipulation

motion, before grasping an object, the robot needs to open the gripper. This information

is contained in the transition that leads to a pregrasp waypoint state. The direct path

should therefore have access to the transition.

The information is stored in the hpp::manipulation::ConstraintSet.

of the path and is accessible via method hpp::manipulation::ConstraintSet::edge

If the path vector is produced by a manipulation planner, each direct path has been created

by a transition. However, the path may later be cut by random shortcut or due to collision and

the associated transition become irrelevant. For example if a path is created by a transition

that leads to a pre-grasp, and cut due to a collision, the path does not reach the target

state and the relevant transition is not the one that built the path.

This class takes a hpp::core::PathVector as input an relabel

each direct path with the correct transition.

Precondition — The path should have been created by a manipulation planning algorithm: in other

words, the constraint set of each direct path should be of type

hpp::manipulation::ConstraintSet.

defDescription
def init(self, arg2: object) -> object

Graph

Description of the constraint graph.

This class contains a graph representing a a manipulation problem

One must make sure not to create loop with shared pointers. To ensure that, the classes are defined as follow:

A Graph owns (i.e. has a shared pointer to) the StateSelector s

A StateSelector owns the Node s related to one gripper.

A State owns its outgoing Edge s.

An Edge does not own anything.

The graph and all its components have a unique index starting at 0 for the graph itself. The index of a component can be retrieved using method GraphComponent::id.

defDescription
def init(self, arg2: str, arg3: Device, arg4: Problem) -> None
def _get_native_graph(self) -> objectReturn a capsule wrapping the native C++ Graph object (for external interop).
def addLevelSetFoliation(self, arg2: Transition, arg3: list, arg4: list) -> NoneAdd the numerical constraints to a LevelSetTransition that create the foliation.
def addNumericalConstraint(self, arg2: State, arg3: pyhpp.constraints.bindings.Implicit) -> NoneAdd a numerical constraint to a state.
def addNumericalConstraintsForPath(self, arg2: State, arg3: list) -> NoneAdd numerical constraints for path to a state.
def addNumericalConstraintsToGraph(self, arg2: list) -> NoneAdd a list of numerical constraints to all transitions in the graph.
def addNumericalConstraintsToState(self, arg2: State, arg3: list) -> NoneAdd numerical constraints to a state.
def addNumericalConstraintsToTransition(self, arg2: Transition, arg3: list) -> NoneAdd numerical constraints to a TRANSITION.
def applyLeafConstraints(self, arg2: Transition, arg3: numpy.ndarray, arg4: numpy.ndarray) -> tupleApply transition constraints to a configuration. Returns tuple with success flag, output configuration, and error norm. If success, the output configuration is reachable from q_rhs along the transition.
def applyStateConstraints(self, arg2: State, arg3: numpy.ndarray) -> tupleApply constraints to a configuration. Returns tuple with success flag, output configuration, and error norm.
def createGraspConstraint(self, arg2: str, arg3: str, arg4: str) -> listCreate grasp, complement and hold constraints for a gripper-handle pair. Returns a list [grasp, complement, hold].
def createLevelSetTransition(self, arg2: State, arg3: State, arg4: str, arg5: pyhpp.core.path.bindings.SplineB3, arg6: State) -> TransitionCreate a LevelSetTransition. See documentation of class hpp::manipulation::graph::LevelSetEdge for more information.
@staticmethod
def createPlacementConstraint(*args, **kwargs)
Create placement constraint between object surfaces and environment surfaces. Creates constraints that ensure proper contact between object and environment.
def createPreGraspConstraint(self, arg2: str, arg3: str, arg4: str) -> pyhpp.constraints.bindings.ImplicitCreate a pre-grasp constraint for a gripper-handle pair.
@staticmethod
def createPrePlacementConstraint(*args, **kwargs)
Create pre-placement constraint with specified width margin. Used for approaching placement configurations before final placement.
def createState(self, arg2: str, arg3: bool, arg4: pyhpp.core.path.bindings.SplineB3) -> StateCreate one or several states. The order is important - the first should be the most restrictive one as a configuration will be in the first state for which the constraints are satisfied.
def createSubGraph(self, arg2: str, arg3: pyhpp.core.bindings.Roadmap) -> NoneCreate a subgraph with guided state selection.
def createTransition(self, arg2: State, arg3: State, arg4: str, arg5: pyhpp.core.path.bindings.SplineB3, arg6: State) -> TransitionCreate a transition. The weights define the probability of selecting a transition among all the outgoing transitions of a state. The probability of a transition is w_i / sum(w_j), where each w_j corresponds to an outgoing transition from a given state. To have a transition that cannot be selected by the M-RRT algorithm but is still acceptable, set its weight to zero.
def createWaypointTransition(self, arg2: State, arg3: State, arg4: str, arg5: pyhpp.core.path.bindings.SplineB3, arg6: pyhpp.core.path.bindings.SplineB3, arg7: State, arg8: bool) -> TransitionCreate a WaypointTransition. See documentation of class hpp::manipulation::graph::WaypointEdge for more information.
def display(self, arg2: str) -> NoneDisplay the current graph. The graph is printed in DOT format.
def displayStateConstraints(self, arg2: State) -> strPrint set of constraints relative to a state in a string.
def displayTransitionConstraints(self, arg2: Transition) -> strPrint set of constraints relative to a transition in a string.
def displayTransitionTargetConstraints(self, arg2: Transition) -> strPrint set of constraints relative to a transition in a string.
@typing.overload
def errorThreshold(self) -> float

@typing.overload
def errorThreshold(self, arg2: float) -> None
Get error threshold in config projector.
def generateTargetConfig(self, arg2: Transition, arg3: numpy.ndarray, arg4: numpy.ndarray) -> tupleGenerate configuration in destination state on a given leaf. Returns tuple with success flag, output configuration, and error norm. Computes a configuration in the destination state of the transition, reachable from q_rhs.
def getConfigErrorForState(self, arg2: State, arg3: numpy.ndarray) -> tupleGet error of a config with respect to a state constraint. Returns whether the configuration belongs to the state. Calls core::ConstraintSet::isSatisfied for the state constraints.
def getConfigErrorForTransition(self, arg2: Transition, arg3: numpy.ndarray) -> tupleGet error of a config with respect to a transition constraint. Returns whether the configuration belongs to the transition. Calls core::ConfigProjector::rightHandSideFromConfig with the input configuration and then core::ConstraintSet::isSatisfied on the transition constraints.
def getConfigErrorForTransitionLeaf(self, arg2: Transition, arg3: numpy.ndarray, arg4: numpy.ndarray) -> tupleGet error of a config with respect to a transition foliation leaf. Returns whether config can be the end point of a path of the transition starting at leafConfig.
def getConfigErrorForTransitionTarget(self, arg2: Transition, arg3: numpy.ndarray, arg4: numpy.ndarray) -> tupleGet error of a config with respect to the target of a transition foliation leaf. Returns whether config can be the end point of a path of the transition starting at leafConfig.
def getContainingNode(self, arg2: Transition) -> strGet the name of the state in which a transition is. Paths satisfying the transition constraints satisfy the state constraints.
def getNodesConnectedByTransition(self, arg2: Transition) -> tupleGet the names of the states connected by a transition.
def getNumericalConstraintsForEdge(self, arg2: Transition) -> listGet numerical constraints of an edge.
def getNumericalConstraintsForGraph(self) -> listGet numerical constraints of the graph.
def getNumericalConstraintsForState(self, arg2: State) -> listGet numerical constraints of a state.
def getRelativeMotionMatrix(self, arg2: Transition) -> listGet relative motion matrix for a transition as list of lists.
def getSecurityMarginMatrixForTransition(self, arg2: Transition) -> listGet security margin matrix for a transition as list of lists.
def getState(self, arg2: str) -> StateReturn the state with the given name.
def getStateFromConfiguration(self, arg2: numpy.ndarray) -> strGet the name of the state corresponding to the configuration.
def getStateNames(self) -> listReturn a list of state names.
def getStates(self) -> listReturn a list of all states in the constraint graph.
def getTransition(self, arg2: str) -> TransitionReturn the transition with the given name.
def getTransitionNames(self) -> listReturn a list of transition names.
def getTransitions(self) -> listReturn a list of all transitions in the constraint graph.
def getWeight(self, arg2: Transition) -> intGet weight of a transition.
def initialize(self) -> NoneInitialize the graph. Performs final initialization of the constraint graph.
def isShort(self, arg2: Transition) -> boolCheck if a transition is short.
@typing.overload
def maxIterations(self) -> int

@typing.overload
def maxIterations(self, arg2: int) -> None
Get maximal number of iterations in config projector.
def registerConstraints(self, arg2: pyhpp.constraints.bindings.Implicit, arg3: pyhpp.constraints.bindings.Implicit, arg4: pyhpp.constraints.bindings.Implicit) -> NoneRegister constraints in the graph.
def removeCollisionPairFromTransition(self, arg2: Transition, arg3: str, arg4: str) -> NoneRemove collision pairs from a transition.
def resetConstraints(self, arg2: State) -> NoneReset constraints of a state.
def setContainingNode(self, arg2: Transition, arg3: State) -> NoneSet in which state a transition is. Paths satisfying the transition constraints satisfy the state constraints.
def setSecurityMarginForTransition(self, arg2: Transition, arg3: str, arg4: str, arg5: float) -> NoneSet collision security margin for a pair of joints along a transition.
def setShort(self, arg2: Transition, arg3: bool) -> NoneSet that a transition is short. When a transition is tagged as short, extension along this transition is done differently in RRT-like algorithms. Instead of projecting a random configuration in the destination state, the configuration to extend itself is projected in the destination state. This makes the rate of success higher.
def setTargetNodeList(self, arg2: list) -> NoneSet the target state list for guided state selection.
def setWaypoint(self, arg2: Transition, arg3: pyhpp.core.path.bindings.SplineB3, arg4: Transition, arg5: State) -> NoneSet waypoint configuration for a waypoint transition. Configures which edge and state to use at the specified waypoint index.
def setWeight(self, arg2: Transition, arg3: pyhpp.core.path.bindings.SplineB3) -> NoneSet weight of a transition. You cannot set weight for waypoint transitions.
@staticmethod
def transitionAtParam(arg1: pyhpp.core.path.bindings.Vector, arg2: float) -> Transition
Return the transition used at a given parameter on a path (static method).
@property
def robot(*args, **kwargs)

@robot.setter
def robot(*args, **kwargs)
The robot device of the constraint graph.

GraphSteeringMethod

defDescription
def init(self, arg2: pyhpp.core.bindings.SteeringMethod) -> None

Handle

Frame attached to an object that is aimed at being grasped

Together with a hpp::pinocchio::Gripper, a handle defines a grasp. A vector of 6 Boolean values called a mask can be passed to the constructor to define the symmetries of the handle. For example, {True,True,True,False,True,True} means that the handle can be grasped with free orientation around x-axis. See https://hal.laas.fr/hal-02995125v2 for details. The setter method mask allows users to define the mask.

Along motions where the handle is grasped by a gripper, an additional constraint is enforced, called the complement constraint. This latter constraint ensures that the object is rigidly fixed to the gripper.

However, for some applications, the complement constraint can be customized using setter maskComp. Note that calling setter method mask reinitializes the mask complement.

defDescription
def createGrasp(self, gripper: pyhpp.pinocchio.bindings.Gripper, name: str) -> pyhpp.constraints.bindings.Implicitgripper — object containing the gripper information
def createGraspAndComplement(self, gripper: pyhpp.pinocchio.bindings.Gripper, name: str) -> pyhpp.constraints.bindings.Implicitgripper — object containing the gripper information
def createGraspComplement(self, gripper: pyhpp.pinocchio.bindings.Gripper, name: str) -> pyhpp.constraints.bindings.Implicitgripper — object containing the gripper information
def createPreGrasp(self, gripper: pyhpp.pinocchio.bindings.Gripper, shift: float, name: str) -> pyhpp.constraints.bindings.Implicitgripper — object containing the gripper information
def getParentJointId(self) -> intGet index of the joint the handle is attached to in pinocchio Model
@property
def approachingDirection(*args, **kwargs)

@approachingDirection.setter
def approachingDirection(*args, **kwargs)
Approaching direction for pregrasp (unit vector in handle frame, default is x-axis).
@property
def clearance(*args, **kwargs)

@clearance.setter
def clearance(*args, **kwargs)
Distance from the center of the gripper along x-axis that ensures no collision. Also gives an order of magnitude of the gripper size.
@property
def localPosition(*args, **kwargs)

@localPosition.setter
def localPosition(*args, **kwargs)
Local position of the handle in the joint frame.
@property
def mask(self) -> list

@mask.setter
def mask(self, value: list[bool]) -> None
Constraint mask: vector<bool> of size 6 defining the symmetries of the handle. See Handle class documentation for details.
@property
def maskComp(*args, **kwargs)

@maskComp.setter
def maskComp(*args, **kwargs)
Mask of the complement constraint.
@property
def name(*args, **kwargs)

@name.setter
def name(*args, **kwargs)
Name of the handle.

HandleMap

defDescription
def contains(self, arg2: object) -> bool
def delitem(self, key: str) -> None
def getitem(self, key: str) -> Handle
def init(self) -> None
def iter(self) -> typing.Iterator[str]
def len(self) -> int
def setitem(self, key: str, value: Handle) -> None

ManipulationPlanner

Inherits: pyhpp.core.bindings.PathPlanner

defDescription
def init(self, arg2: pyhpp.core.bindings.Problem) -> None

Problem

Inherits: pyhpp.core.bindings.Problem

defDescription
def init(self, arg2: Device) -> None
def checkProblem(self) -> NoneCheck whether the problem is well formulated.
@typing.overload
def constraintGraph(self) -> Graph

@typing.overload
def constraintGraph(self, arg2: Graph) -> None
Get the graph of constraints.
def fullSteeringMethod(self, arg2: pyhpp.core.bindings.SteeringMethod) -> NoneSet the problem steering method directly. Unlike steeringMethod, this does not wrap the given steering method in a manipulation graph steering method.
@typing.overload
def steeringMethod(self) -> pyhpp.core.bindings.SteeringMethod

@typing.overload
def steeringMethod(self, arg2: pyhpp.core.bindings.SteeringMethod) -> None
Get the inner steering method (unwrapped from the graph steering method if applicable).

RandomShortcut

Inherits: pyhpp.core.bindings.PathOptimizer

defDescription
def init(self, arg2: object) -> object

SplineGradientBased_bezier1

Inherits: pyhpp.core.bindings.PathOptimizer

defDescription
def init(self, arg2: pyhpp.core.bindings.Problem) -> object
@property
def QPAccuracy(self) -> float

@QPAccuracy.setter
def QPAccuracy(self, arg2: float) -> None
@property
def alphaInit(self) -> float

@alphaInit.setter
def alphaInit(self, arg2: float) -> None
@property
def alwaysStopAtFirst(self) -> bool

@alwaysStopAtFirst.setter
def alwaysStopAtFirst(self, arg2: bool) -> None
@property
def checkJointBound(self) -> bool

@checkJointBound.setter
def checkJointBound(self, arg2: bool) -> None
@property
def costOrder(self) -> int

@costOrder.setter
def costOrder(self, arg2: int) -> None
@property
def costThreshold(self) -> float

@costThreshold.setter
def costThreshold(self, arg2: float) -> None
@property
def guessThreshold(self) -> float

@guessThreshold.setter
def guessThreshold(self, arg2: float) -> None
@property
def linearizeAtEachStep(self) -> bool

@linearizeAtEachStep.setter
def linearizeAtEachStep(self, arg2: bool) -> None
@property
def reorderIntervals(self) -> bool

@reorderIntervals.setter
def reorderIntervals(self, arg2: bool) -> None
@property
def returnOptimum(self) -> bool

@returnOptimum.setter
def returnOptimum(self, arg2: bool) -> None
@property
def usePathLengthAsWeights(self) -> bool

@usePathLengthAsWeights.setter
def usePathLengthAsWeights(self, arg2: bool) -> None

SplineGradientBased_bezier3

Inherits: pyhpp.core.bindings.PathOptimizer

defDescription
def init(self, arg2: pyhpp.core.bindings.Problem) -> object
@property
def QPAccuracy(self) -> float

@QPAccuracy.setter
def QPAccuracy(self, arg2: float) -> None
@property
def alphaInit(self) -> float

@alphaInit.setter
def alphaInit(self, arg2: float) -> None
@property
def alwaysStopAtFirst(self) -> bool

@alwaysStopAtFirst.setter
def alwaysStopAtFirst(self, arg2: bool) -> None
@property
def checkJointBound(self) -> bool

@checkJointBound.setter
def checkJointBound(self, arg2: bool) -> None
@property
def costOrder(self) -> int

@costOrder.setter
def costOrder(self, arg2: int) -> None
@property
def costThreshold(self) -> float

@costThreshold.setter
def costThreshold(self, arg2: float) -> None
@property
def guessThreshold(self) -> float

@guessThreshold.setter
def guessThreshold(self, arg2: float) -> None
@property
def linearizeAtEachStep(self) -> bool

@linearizeAtEachStep.setter
def linearizeAtEachStep(self, arg2: bool) -> None
@property
def reorderIntervals(self) -> bool

@reorderIntervals.setter
def reorderIntervals(self, arg2: bool) -> None
@property
def returnOptimum(self) -> bool

@returnOptimum.setter
def returnOptimum(self, arg2: bool) -> None
@property
def usePathLengthAsWeights(self) -> bool

@usePathLengthAsWeights.setter
def usePathLengthAsWeights(self, arg2: bool) -> None

State

State of an end-effector.

States of the graph of constraints. There is one graph for each end-effector.

defDescription
def configConstraint(self) -> pyhpp.core.bindings.ConstraintSet
def id(self) -> intReturn the component id.
def name(self) -> strGet the component name.
def neighborEdges(self) -> listGet the list of edges connected to this state.

StatesPathFinder

Inherits: pyhpp.core.bindings.PathPlanner

defDescription
def init(self, arg2: pyhpp.core.bindings.Problem) -> None

Transition

Transition between two states of a constraint graph

An edge stores two types of constraints.

Path constraints should be safisfied by paths belonging to the edge. Along any path, the right hand side of the constraint is constant, but can differ between paths. For instance if an edge represents a transit path of a robot that can grasp an object, the right hand side of the constraint represents the position of the object. Along any transit path, the object does not move, but for different paths the object can be at different positions. method pathConstraint.

Configuration constraints are constraints that configurations in the destination state should satisfy and the constraints that paths should satisfy. For instance, if the edge links a state where the robot does not hold the object to a state where the robot holds the object, the configuration constraints represent a fixed relative position of the object with respect to the gripper and a stable position of the object. Configuration constraints are necessary to generate a configuration in the destination state of the edge that is reachable from a given configuration in the start state by an admissible path.

defDescription
def id(self) -> intReturn the component id.
def isWaypointTransition(self) -> boolError — Could not find member (.*) isWaypointEdge of class hpp::manipulation::graph::Edge
def name(self) -> strGet the component name.
@typing.overload
def nbWaypoints(self) -> int

@typing.overload
def nbWaypoints(self) -> int
Error — Could not find member (.*) nbWaypoints of class hpp::manipulation::graph::Edge
def pathValidation(self) -> pyhpp.core.bindings.PathValidationGet path validation associated to the edge.
def waypoint(self, arg2: pyhpp.core.path.bindings.SplineB3) -> TransitionError — Could not find member (.*) waypoint of class hpp::manipulation::graph::Edge

TransitionPlanner

Inherits: pyhpp.core.bindings.PathPlanner

Plan paths in a leaf of a transition

In many manipulation applications, the sequence of actions is knwown in advance or computed by a task planner. There is a need then to connect configurations that lie on the same leaf of a transition. This class performs this computation.

The constraint graph is stored in the Problem instance of the planner. To select the transition, call method setEdge with the index of the transition.

At construction, a core::Problem instance is created, as well as a core::PathPlanner instance. They are respectively called the inner problem and the inner planner.

In order to take into account security margins, when selecting a transition, the list of configuration validations passed to the inner problem are

the PathValidation instance of the transition, cast into core::ConfigValidation type

a core::JointBoundValidation instance.

The leaf of the transition is defined by the initial configuration passed to method planPath . The right hand side of the inner problem constraints is initialized with this configuration.

The class stores path optimizers that are called when invoking method optimizePath .

Method timeParameterization computes a time parameterization of a given path.

defDescription
def init(self, arg2: pyhpp.core.bindings.Problem) -> None
def addPathOptimizer(self, pathOptimizer: pyhpp.core.bindings.PathOptimizer) -> None
def clearPathOptimizers(self) -> NoneClear path optimizers.
def computePath(self, arg2: numpy.ndarray, arg3: numpy.ndarray, self_: bool) -> pyhpp.core.path.bindings.Vector
def directPath(self, arg2: numpy.ndarray, arg3: numpy.ndarray, arg4: bool) -> tupleCompute a direct path on a transition. Returns (success, path, status).
@typing.overload
def innerPlanner(self) -> pyhpp.core.bindings.PathPlanner

@typing.overload
def innerPlanner(self, arg2: pyhpp.core.bindings.PathPlanner) -> None
Get the inner planner.
def innerProblem(self) -> pyhpp.core.bindings.ProblemGet the inner problem.
def optimizePath(self, path: pyhpp.core.bindings.Path) -> pyhpp.core.path.bindings.Vector:param :input path
def pathProjector(self, pathProjector: pyhpp.core.bindings.PathProjector) -> NoneSet the path projector.
def planPath(self, qInit: numpy.ndarray, qGoals: numpy.ndarray, resetRoadmap: bool) -> pyhpp.core.path.bindings.VectorqInit — initial configuration, :param qGoals goal:configurations, resetRoadmap — whether to reset the roadmap
def setEdge(self, id: Transition) -> Noneid — index of the transition in the constraint graph
def setReedsAndSheppSteeringMethod(self, turningRadius: float) -> NoneCreate a Reeds and Shepp steering method and path it to the problem.
def setTransition(self, id: Transition) -> Noneid — index of the transition in the constraint graph
def timeParameterization(self, path: pyhpp.core.path.bindings.Vector) -> pyhpp.core.path.bindings.Vector:param :input path
def validateConfiguration(self, arg2: numpy.ndarray, arg3: int) -> tupleValidate configuration against the graph state identified by id. Returns (valid, report).

map_indexing_suite_HandleMap_entry

defDescription
def init(self) -> None
def repr(self) -> object
def data(self) -> Handle
def key(self) -> str

modelsInfo

defDescription
def init(self) -> None
@property
def pose(self) -> pinocchio.pinocchio_pywrap_default.SE3

@pose.setter
def pose(self, arg2: pinocchio.pinocchio_pywrap_default.SE3) -> None
@property
def prefix(self) -> str

@prefix.setter
def prefix(self, arg2: str) -> None
@property
def srdfPath(self) -> str

@srdfPath.setter
def srdfPath(self, arg2: str) -> None
@property
def urdfPath(self) -> str

@urdfPath.setter
def urdfPath(self, arg2: str) -> None

modelsInfoVec

defDescription
def contains(self, arg2: object) -> bool
def delitem(self, arg2: object) -> None
def getitem(self, arg2: object) -> object
def init(self) -> None
def iter(self) -> object
def len(self) -> int
def setitem(self, arg2: object, arg3: object) -> None
def append(self, arg2: object) -> None
def extend(self, arg2: object) -> None

pyhpp.manipulation.urdf

Functions

defDescription
def loadModel(arg1: pyhpp.manipulation.bindings.Device, arg2: int, arg3: str, arg4: str, arg5: str, arg6: str, arg7: pinocchio.pinocchio_pywrap_default.SE3) -> NoneLoad a robot model from URDF/SRDF files into a manipulation Device, also parsing grasp/contact data from the SRDF.
def loadModelFromString(arg1: pyhpp.manipulation.bindings.Device, arg2: int, arg3: str, arg4: str, arg5: str, arg6: str, arg7: pinocchio.pinocchio_pywrap_default.SE3) -> NoneLoad a robot model from URDF/SRDF XML strings into a manipulation Device, also parsing grasp/contact data from the SRDF.

pyhpp.manipulation.steering_method

Functions

defDescription
def makePiecewiseLinearTrajectory(arg1: numpy.ndarray, arg2: numpy.ndarray) -> pyhpp.core.bindings.PathBuild a piecewise linear path. See C++ documentation of class hpp::manipulation::steeringMethod::Cartesian.

Cartesian

Build a robot trajectory from an end-effector trajectory

This class does not derive from SteeringMethod since it does not link two configurations by a path. Instead, it only takes an initial configuration and a trajectory of an end-effector.

To use this class, the user needs to provide

a constraint with value in . An easy way to create such a constraint is to use method hpp::manipulation::Handle::createGrasp. The constraint is passed to this class using method trajectoryConstraint .

the time-varying right hand side of this constraint along the path the user wants to create in the form of a hpp::core::Path instance with values in . For that, makePiecewiseLinearTrajectory method may be useful.

Once the steering method has been initialized, it can be called with and initial configuration q_init. The interval of definition of the output path is the same as the one of the path provided as the right hand side of the constraint. Note that q_init should satisfy the constraint at times 0.

defDescription
def init(self, arg2: pyhpp.core.bindings.Problem) -> None
def getRightHandSide(self) -> pyhpp.constraints.bindings.DifferentiableFunctionGet right hand side function of trajectory constraint.
def planPath(self, arg2: numpy.ndarray) -> tuplePlan a path starting from an initial configuration.
@typing.overload
def setRightHandSide(self, arg2: pyhpp.core.bindings.Path, arg3: bool) -> None

@typing.overload
def setRightHandSide(self, arg2: pyhpp.constraints.bindings.DifferentiableFunction, arg3: pyhpp.core.bindings.interval) -> None
Set right hand side from a hpp::core::Path
def timeRange(self) -> pyhpp.core.bindings.intervalGet interval of definition of right hand side of trajectory constraint.
@property
def errorThreshold(*args, **kwargs)

@errorThreshold.setter
def errorThreshold(*args, **kwargs)
Error threshold of numerical solver.
@property
def maxIterations(*args, **kwargs)

@maxIterations.setter
def maxIterations(*args, **kwargs)
Maximal number of iterations of numerical solver.
@property
def nDiscreteSteps(*args, **kwargs)

@nDiscreteSteps.setter
def nDiscreteSteps(*args, **kwargs)
Number of discretization steps in the interval of definition where configurations are computed.
@property
def trajectoryConstraint(*args, **kwargs)

@trajectoryConstraint.setter
def trajectoryConstraint(*args, **kwargs)
Constraint with a time-varying right hand side.

pyhpp.pinocchio

ComputationFlag

Inherits: int


Device

Robot with geometric and dynamic pinocchio.

The creation of the device is done by Device::create(const

std::string name). This function returns a shared pointer to the newly created object. Smart pointers documentation: http://www.boost.org/libs/smart_ptr/smart_ptr.htm

defDescription
def init(self, arg2: str) -> object
def computeForwardKinematics(self, self_: int) -> NoneCompute forward kinematics computing everything.
def computeFramesForwardKinematics(self) -> None
def configSize(self) -> int
def configSpace(self) -> LiegroupSpaceReturns a LiegroupSpace representing the configuration space.
@typing.overload
def currentConfiguration(self) -> numpy.ndarray

@typing.overload
def currentConfiguration(self, arg2: numpy.ndarray) -> bool
Get current configuration.
def data(self) -> pinocchio.pinocchio_pywrap_default.Data
def geomData(self) -> pinocchio.pinocchio_pywrap_default.GeometryData
def geomModel(self) -> pinocchio.pinocchio_pywrap_default.GeometryModel
def getCenterOfMass(self) -> numpy.ndarray
def getJointPosition(self, arg2: str) -> list
def getJointsPosition(self, arg2: numpy.ndarray, arg3: list) -> list
def model(self) -> pinocchio.pinocchio_pywrap_default.Model
def name(self) -> strGet name of device.
def numberDof(self) -> int
def removeJoints(self, arg2: pinocchio.pinocchio_pywrap_default.StdVec_StdString, arg3: numpy.ndarray) -> None
def setJointBounds(self, arg2: str, arg3: list) -> None
def updateGeometryPlacements(self) -> NoneUpdate the geometry placement to the currentConfiguration.
def visualModel(self) -> pinocchio.pinocchio_pywrap_default.GeometryModel
@property
def rankInConfiguration(self) -> dict

Gripper

Definition of a robot gripper

This class represent a robot gripper as a frame attached to the joint of the robot that holds the gripper.

To graps a box-shaped object with small lengths along x and y, the gripper frame should coincide with the object frame.

defDescription
def getParentJointId(self) -> intGet index of the joint the handle is attached to in pinocchio Model
def name(self) -> str
@property
def clearance(self) -> float

@clearance.setter
def clearance(self, arg2: float) -> None
@property
def localPosition(self) -> pinocchio.pinocchio_pywrap_default.SE3

GripperMap

defDescription
def contains(self, arg2: object) -> bool
def delitem(self, key: str) -> None
def getitem(self, key: str) -> Gripper
def init(self) -> None
def iter(self) -> typing.Iterator[str]
def len(self) -> int
def setitem(self, key: str, value: Gripper) -> None

LiegroupElement

hpp::pinocchio::LiegroupElement

defDescription
def add(self, arg2: numpy.ndarray) -> object
@typing.overload
def init(self, arg2: numpy.ndarray, arg3: LiegroupSpace) -> None

@typing.overload
def init(self, arg2: LiegroupSpace) -> None
def str(self) -> str
def sub(self, arg2: LiegroupElement) -> object
def space(self) -> LiegroupSpacelist index out of range
def vector(self) -> numpy.ndarraylist index out of range
@property
def v(self) -> numpy.ndarray

@v.setter
def v(self, arg2: numpy.ndarray) -> None

LiegroupElementRef

hpp::pinocchio::LiegroupElementRef

defDescription
def add(self, arg2: numpy.ndarray) -> object
def init(self, arg2: numpy.ndarray, arg3: LiegroupSpace) -> None
def str(self) -> str
def sub(self, arg2: LiegroupElementRef) -> object
def space(self) -> LiegroupSpacelist index out of range
def vector(self) -> numpy.ndarraylist index out of range
@property
def v(self) -> numpy.ndarray

@v.setter
def v(self, arg2: numpy.ndarray) -> None

LiegroupSpace

Cartesian product of elementary Lie groups

Some values produced and manipulated by functions belong to Lie groups For instance rotations, rigid-body motions are element of Lie groups.

Elements of Lie groups are usually applied common operations, like

integrating a velocity from a given element during unit time,

computing the constant velocity that moves from one element to another one in unit time.

By analogy with vector spaces that are a particular type of Lie group, the above operations are implemented as operators + and - respectively acting on LiegroupElement instances.

This class represents a Lie group as the cartesian product of elementaty Lie groups. Those elementary Lie groups are gathered in a variant called LiegroupType.

Elements of a Lie group are represented by class LiegroupElement.

defDescription
@staticmethod
def R1(rotation: bool) -> LiegroupSpace
rotation — whether values of this space represent angles or lengths.
@staticmethod
def R2() -> LiegroupSpace
Return as a Lie group.
@staticmethod
def R2xSO2() -> LiegroupSpace
Return .
@staticmethod
def R3() -> LiegroupSpace
Return as a Lie group.
@staticmethod
def R3xSO3() -> LiegroupSpace
Return .
@staticmethod
def Rn(n: int) -> LiegroupSpace
n — dimension of vector space
@staticmethod
def SE2() -> LiegroupSpace
Return .
@staticmethod
def SE3() -> LiegroupSpace
Return .
def eq(self, arg2: LiegroupSpace) -> object
def imul(self, arg2: LiegroupSpace) -> LiegroupSpace
def mul(self, arg2: LiegroupSpace) -> LiegroupSpace
def ne(self, arg2: LiegroupSpace) -> object
def str(self) -> str
def dDifference_dq0(self, arg2: object, arg3: numpy.ndarray, arg4: numpy.ndarray, arg5: numpy.ndarray) -> None
def dDifference_dq1(self, arg2: object, arg3: numpy.ndarray, arg4: numpy.ndarray, arg5: numpy.ndarray) -> None
@staticmethod
def dIntegrate_dq(arg1: object, arg2: object, arg3: numpy.ndarray, arg4: numpy.ndarray) -> None
@staticmethod
def dIntegrate_dv(arg1: object, arg2: object, arg3: numpy.ndarray, arg4: numpy.ndarray) -> None
@staticmethod
def empty() -> LiegroupSpace
Return empty Lie group.
def mergeVectorSpaces(self) -> None
def name(self) -> strReturn name of Lie group.

map_indexing_suite_GripperMap_entry

defDescription
def init(self) -> None
def repr(self) -> object
def data(self) -> Gripper
def key(self) -> str

pyhpp.pinocchio.urdf

Functions

defDescription
def loadModel(arg1: object, arg2: int, arg3: str, arg4: str, arg5: str, arg6: str, arg7: pinocchio.pinocchio_pywrap_default.SE3) -> None
def loadModelFromString(arg1: object, arg2: int, arg3: str, arg4: str, arg5: str, arg6: str, arg7: pinocchio.pinocchio_pywrap_default.SE3) -> None

HPP-gepetto-viewer

Building Status Pipeline status Coverage report Code style: black pre-commit.ci status

HPP Plot

Pipeline status Coverage report Code style: black pre-commit.ci status

hpp-exec

ROS2 execution utilities for HPP-generated trajectories.

Overview

You write your HPP planning script using pyhpp directly, then use hpp_exec to send the trajectory to ros2_control.

Tutorials

The official tutorials for this package are in hpp-tutorial:

  • Tutorial 6: Plan a simple arm motion and execute on Gazebo via send_trajectory()
  • Tutorial 7: Pick-and-place with graph segments, gripper actions, and execute_segments()
  • Tutorial 8: Pick-and-place while opening the gripper during arm travel

Documentation

Creating configs and times from HPP

After planning and time parameterization with HPP, you have a Path object that maps time (seconds) to robot configurations. For a plain arm trajectory, sample it at regular intervals to get configs:

import numpy as np
from pyhpp.core import TrapezoidalTimeParameterization

# After solving:
# path = planner.solve()
optimizer = TrapezoidalTimeParameterization(problem)
optimizer.maxVelocity = 0.5
optimizer.maxAcceleration = 0.5
p_timed = optimizer.optimize(path)

n_samples = 50
configs = []
times = []

for i in range(n_samples + 1):
    t = (i / n_samples) * p_timed.length()
    q, success = p_timed(t)
    if success:
        configs.append(np.array(q))
        times.append(t)

# configs: List[np.ndarray] - configuration vectors at each sample
# times: List[float] - timestamps in seconds

The HPP configuration vector typically includes all robot DOFs. Use joint_indices to select which joints to send to ros2_control (e.g., arm joints only, excluding fingers).

Sending to ros2_control

from hpp_exec import send_trajectory

send_trajectory(
    configs, times,
    joint_names=["joint1", "joint2", ...],  # ROS2 joint names
    joint_indices=list(range(7)),            # Which HPP config indices to use
)

Installation

cd hpp-exec
./run.sh

# First time inside container:
cd ~/devel/src && make all

API

from hpp_exec import (
    BackgroundAction,
    Segment,
    execute_segments,
    read_current_configuration,
    segments_by_transition,
    print_segments,
    send_trajectory,
    segments_from_graph,
)

# Main function - send trajectory to ros2_control
send_trajectory(
    configs,              # List[np.ndarray] from HPP
    times,                # List[float] timestamps in seconds
    joint_names,            # List[str] ROS2 joint names
    controller_topic="...", # FollowJointTrajectory action topic
)

# Expose the HPP graph segments.
configs, times, segments = segments_from_graph(path, graph)
print_segments(segments)

# Inspect every occurrence of each graph transition.
segments_by_name = segments_by_transition(segments)
segments_by_name["fr3/gripper > box/handle | f_23"][0].pre_actions.append(grasp_box)
segments_by_name["fr3/gripper < box/handle | 0-0_21"][0].pre_actions.append(
    release_box
)

# Or overlap a blocking action with the next segment's arm motion.
background_open = BackgroundAction(open_gripper, name="open_gripper")
segments[0].pre_actions.append(background_open.start)
segments[2].pre_actions.append(background_open.wait)
segments[2].pre_actions.append(close_gripper)

execute_segments(
    segments,
    configs,
    times,
    joint_names,
)

# Dictionary API: instead of the manual appends above, leave segments
# unchanged and attach actions by graph transition name when starting execution.
# This applies each action to every segment with that transition name.
pre_actions = {
    "fr3/gripper > box/handle | f_23": [grasp_box],
}
post_actions = {
    "fr3/gripper < box/handle | 0-0_21": [release_box],
}

execute_segments(
    segments,
    configs,
    times,
    joint_names,
    pre_actions_by_transition=pre_actions,
    post_actions_by_transition=post_actions,
)

# Read the robot state before planning from the live position.
q_start = read_current_configuration(
    node,
    joint_names=["joint1", "joint2", ...],
    topic="/joint_states",
)

See the generated Doxygen documentation for send_trajectory_async(), configs_to_joint_trajectory(), and other lower-level helpers.

Tutorials

The maintained end-to-end examples live in hpp_tutorial.

cd ~/devel/src/hpp_tutorial/tutorial_6
python -i init.py

See tutorial 6 for simple arm execution, tutorial 7 for pick-and-place with graph segments, and tutorial 8 for overlapping a gripper action with arm travel.

Structure

hpp-exec/
|-- hpp_exec/           # Python package
|   |-- __init__.py
|   |-- actions.py         # Reusable helpers for segment actions
|   |-- joint_state.py     # Read JointState messages as ordered configs
|   |-- segments.py        # Segment data structure
|   |-- trajectory_utils.py # HPP config to ROS2 JointTrajectory conversion
|   |-- ros2_sender.py     # send_trajectory() via FollowJointTrajectory action
|   `-- graph_segments.py         # Graph segment extraction and display
|-- scripts/               # Launch scripts for Gazebo
|-- robots/                # URDF/SRDF assets
|-- docker/
|-- Dockerfile
`-- run.sh

License

BSD-2-Clause