Skip to content

Pr humble python bindings #3487

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 30 commits into
base: humble
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
cceb155
Add initial set of Python bindings
SamueleSandrini May 20, 2025
c4da4f1
Add remaining Python bindings
SamueleSandrini May 21, 2025
0c8e455
Add remaining Python bindings
SamueleSandrini May 21, 2025
37350f1
Add init and moveit_py utils
SamueleSandrini May 22, 2025
03695bb
Fix plan method and add PlanSolution binding
SamueleSandrini May 22, 2025
0834aaa
Add initial tests for moveit_py
SamueleSandrini May 26, 2025
8f948a7
Drop PlanningScene changes not relevant to moveit_py
SamueleSandrini May 26, 2025
5da1391
Update moveit_py structure for uniformity
SamueleSandrini May 26, 2025
237f394
Remove comments about missing Humble interfaces
SamueleSandrini May 26, 2025
db1d79e
Add stub files
SamueleSandrini May 26, 2025
c97ec4a
Add Sphinx configuration and index
SamueleSandrini May 26, 2025
72217cc
Apply clang-format to moveit_py
SamueleSandrini May 26, 2025
af08fc7
Apply pre-commit fixes
SamueleSandrini May 26, 2025
2d5fefb
Fix authors in package xml
SamueleSandrini May 26, 2025
959028c
Fix after stub gen, unregistered type RobotTrajectory
SamueleSandrini May 27, 2025
c1457dc
Fix unregistered type MoveItErrorCode
SamueleSandrini May 28, 2025
3fce12b
Fix PlanSolution properties
SamueleSandrini May 28, 2025
b4ea55a
Added readme to moveit_py
SamueleSandrini May 28, 2025
9e944f3
Added readme to moveit_py
SamueleSandrini May 28, 2025
44a4d29
Fix line-ending issues
rhaschke May 30, 2025
c8da3b4
Remove python stuff from moveit_core and moveit_commander
rhaschke May 30, 2025
c527cb8
Delete redundant file
rhaschke May 30, 2025
595d00b
Fix tests
rhaschke May 30, 2025
5c098a2
Merge pull request #1 from rhaschke/pr-humble-python-bindings
SamueleSandrini May 30, 2025
5545889
Fix names and clang-tidy issue
SamueleSandrini May 30, 2025
338f24a
Further reduce differences to main
rhaschke Jun 1, 2025
2771a76
Merge pull request #2 from rhaschke/pr-humble-python-bindings
SamueleSandrini Jun 2, 2025
8f8140e
Reduce stub file differences with main
SamueleSandrini Jun 2, 2025
c050643
Fix authors
SamueleSandrini Jun 2, 2025
2933784
Fix arg name in PlanningScene stub file
SamueleSandrini Jun 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions moveit_py/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
cmake_minimum_required(VERSION 3.22)
project(moveit_py)

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclpy REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(moveit_ros_planning REQUIRED)
find_package(moveit_ros_planning_interface REQUIRED)
find_package(moveit_core REQUIRED)
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
find_package(pybind11_vendor REQUIRED)
find_package(pybind11 REQUIRED)
find_package(Eigen3 REQUIRED)

# enables using the Python extensions from the build space for testing
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_moveit/__init__.py" "")

add_subdirectory(src/moveit/moveit_py_utils)

ament_python_install_package(moveit)

# Set the build location and install location for a CPython extension
function(configure_build_install_location library_name)
# Install into test_moveit folder in build space for unit tests to import
set_target_properties(
${library_name}
PROPERTIES # Use generator expression to avoid prepending a build type
# specific directory on Windows
LIBRARY_OUTPUT_DIRECTORY
$<1:${CMAKE_CURRENT_BINARY_DIR}/test_moveit>
RUNTIME_OUTPUT_DIRECTORY
$<1:${CMAKE_CURRENT_BINARY_DIR}/test_moveit>)

install(TARGETS ${library_name} DESTINATION "${PYTHON_INSTALL_DIR}/moveit")
endfunction()

pybind11_add_module(
core
src/moveit/core.cpp
src/moveit/moveit_core/collision_detection/collision_common.cpp
src/moveit/moveit_core/collision_detection/collision_matrix.cpp
src/moveit/moveit_core/collision_detection/world.cpp
src/moveit/moveit_core/controller_manager/controller_manager.cpp
src/moveit/moveit_core/kinematic_constraints/utils.cpp
src/moveit/moveit_core/planning_interface/planning_response.cpp
src/moveit/moveit_core/planning_scene/planning_scene.cpp
src/moveit/moveit_core/transforms/transforms.cpp
src/moveit/moveit_core/robot_model/joint_model.cpp
src/moveit/moveit_core/robot_model/joint_model_group.cpp
src/moveit/moveit_core/robot_model/robot_model.cpp
src/moveit/moveit_core/robot_state/robot_state.cpp
src/moveit/moveit_core/robot_trajectory/robot_trajectory.cpp
)
target_link_libraries(
core
PRIVATE moveit_ros_planning::moveit_cpp
rclcpp::rclcpp
moveit_core::moveit_transforms
moveit_core::moveit_kinematic_constraints
moveit_core::moveit_planning_interface
moveit_core::moveit_planning_scene
moveit_core::moveit_utils
moveit_core::moveit_robot_model
moveit_core::moveit_robot_state
moveit_py_utils
)
configure_build_install_location(core)

pybind11_add_module(
planning
src/moveit/planning.cpp
src/moveit/moveit_ros/moveit_cpp/moveit_cpp.cpp
src/moveit/moveit_ros/moveit_cpp/planning_component.cpp
src/moveit/moveit_ros/planning_scene_monitor/planning_scene_monitor.cpp
src/moveit/moveit_ros/trajectory_execution_manager/trajectory_execution_manager.cpp
)
target_link_libraries(
planning
PRIVATE moveit_ros_planning::moveit_cpp
moveit_ros_planning::moveit_planning_scene_monitor
moveit_ros_planning::moveit_trajectory_execution_manager
moveit_core::moveit_utils
rclcpp::rclcpp
moveit_py_utils)
configure_build_install_location(planning)

if(BUILD_TESTING)
find_package(ament_cmake_pytest REQUIRED)
set(_pytest_tests test/unit/test_robot_model.py test/unit/test_robot_state.py)
foreach(test_path ${_pytest_tests})
get_filename_component(_test_name ${test_path} NAME_WE)
ament_add_pytest_test(
${_test_name}
${test_path}
APPEND_ENV
AMENT_PREFIX_INDEX=${ament_index_build_path}
PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}
TIMEOUT
60
WORKING_DIRECTORY
"${CMAKE_SOURCE_DIR}")
endforeach()
endif()

ament_export_targets(moveit_py_utilsTargets HAS_LIBRARY_TARGET)
ament_export_dependencies(moveit_ros_planning_interface)
ament_package()
35 changes: 35 additions & 0 deletions moveit_py/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# MoveIt 2 Python Library
<img src="./banner.png" width="50%">

`moveit_py` is a Python library for interfacing with the core functionalities of MoveIt 2.
The goal of this library is to provide a simplified interface for MoveIt 2 Python users.

This Python library depends on [pybind11](https://pybind11.readthedocs.io/en/stable/index.html) for generating Python bindings.
The project is split into the following folders:

├── docs # Sphinx documentation files
├── moveit # Python library stubs; Python functionalities built on top of bindings
├── src/moveit # pybind11 binding code
├── test # Unit and integration testing

## Tutorials
We are continuing to add tutorials for the MoveIt 2 Python library. Of particular note is the fact that one can interact with MoveIt interactively since Python is an interpreted language, our tutorials demonstrate this through leveraging Jupyter notebooks. For further details please consult the [MoveIt 2 tutorials site](https://moveit.picknik.ai/main/index.html).

## Contribution Guidelines
Community contributions are welcome.

For detailed contribution guidelines please consult the official [MoveIt contribution guidelines](https://moveit.ros.org/documentation/contributing/).

## Citing the Library
If you use this library in your work please use the following citation:
```bibtex
@software{fagan2023moveitpy,
author = {Fagan, Peter David},
title = {{MoveIt 2 Python Library: A Software Library for Robotics Education and Research}},
url = {https://github.com/moveit/moveit2/tree/main/moveit_py},
year = {2023}
}
```

## Acknowledgements
Thank you to the [Google Summer of Code program](https://summerofcode.withgoogle.com/) for sponsoring the development of this Python library. Thank you to the MoveIt maintainers Henning Kayser (@henningkayser) and Michael Goerner (@v4hn) for their guidance as supervisors of my GSoC project. Finally thank you to the [ML Collective](https://mlcollective.org/) for providing compute support for this project.
Binary file added moveit_py/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 86 additions & 0 deletions moveit_py/docs/script/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('../../../../../../build/moveit_py'))


# -- Project information -----------------------------------------------------

project = "moveit_py"
copyright = "2022, Peter David Fagan; 2025, Samuele Sandrini"
author = "Peter David Fagan, Samuele Sandrini"


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx.ext.napoleon",
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx_rtd_theme",
"sphinx.ext.intersphinx",
]

intersphinx_mapping = {
"numpy": ("https://numpy.org/doc/stable/", None),
"geometry_msgs": ("http://docs.ros.org/en/latest/api/geometry_msgs/html/", None),
}
autodoc_typehints = "signature"

autodoc_default_options = {
"members": True,
"undoc-members": True,
"member-order": "bysource",
}

autosummary_generate = True

# Napoleon settings
napoleon_google_docstring = True
napoleon_numpy_docstring = False
napoleon_include_init_with_doc = False
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = False
napoleon_use_admonition_for_examples = False
napoleon_use_admonition_for_notes = False
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_param = False
napoleon_use_rtype = False

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]

master_doc = "index"
13 changes: 13 additions & 0 deletions moveit_py/docs/script/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
MoveItPy API Documentation
=====================================

.. toctree::

.. autosummary::
:toctree: _autosummary
:recursive:

moveit_py.core
moveit_py.planning
moveit_py.policies
moveit_py.servo_client
18 changes: 18 additions & 0 deletions moveit_py/moveit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Stubfile Generation
What is a stub?

```
A stub file in Python is a file that is used to define type hinting information (.pyi file extension).
This type hint information enables users to interactively retrieve data about a method or class within their chosem IDE.
```

For this project we leverage (stubgen)[https://mypy.readthedocs.io/en/stable/stubgen.html] from the (mypy)[https://mypy.readthedocs.io/en/stable/index.html]
Python package to autogenerate stub files. To do so we simply build the moveit_py Python library and run the following command from an environment containing the built package:

```
stubgen -p moveit
```

This outputs the outgenerated stub files to an `out` directory. These are the stub files we use.

Note: manual edits are likely to be made to the autogenerated files for official library releases.](https://mypy.readthedocs.io/en/stable/index.html)
3 changes: 3 additions & 0 deletions moveit_py/moveit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from moveit.core import *
from moveit.planning import *
from moveit.utils import get_launch_params_filepaths
3 changes: 3 additions & 0 deletions moveit_py/moveit/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from moveit.core import *
from moveit.planning import *
from moveit.utils import get_launch_params_filepaths as get_launch_params_filepaths
13 changes: 13 additions & 0 deletions moveit_py/moveit/core/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from . import (
collision_detection as collision_detection,
controller_manager as controller_manager,
kinematic_constraints as kinematic_constraints,
planning_interface as planning_interface,
planning_scene as planning_scene,
robot_model as robot_model,
robot_state as robot_state,
robot_trajectory as robot_trajectory,
)

class World:
def __init__(self, *args, **kwargs) -> None: ...
27 changes: 27 additions & 0 deletions moveit_py/moveit/core/collision_detection.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from _typeshed import Incomplete

class AllowedCollisionMatrix:
def __init__(self, *args, **kwargs) -> None: ...
def clear(self, *args, **kwargs): ...
def get_entry(self, *args, **kwargs): ...
def remove_entry(self, *args, **kwargs): ...
def set_entry(self, *args, **kwargs): ...

class CollisionRequest:
contacts: Incomplete
cost: Incomplete
distance: Incomplete
joint_model_group_name: Incomplete
max_contacts: Incomplete
max_contacts_per_pair: Incomplete
max_cost_sources: Incomplete
verbose: Incomplete
def __init__(self, *args, **kwargs) -> None: ...

class CollisionResult:
collision: Incomplete
contact_count: Incomplete
contacts: Incomplete
cost_sources: Incomplete
distance: Incomplete
def __init__(self, *args, **kwargs) -> None: ...
5 changes: 5 additions & 0 deletions moveit_py/moveit/core/controller_manager.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class ExecutionStatus:
def __init__(self, *args, **kwargs) -> None: ...
def __bool__(self) -> bool: ...
@property
def status(self): ...
3 changes: 3 additions & 0 deletions moveit_py/moveit/core/kinematic_constraints.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def construct_constraints_from_node(*args, **kwargs): ...
def construct_joint_constraint(*args, **kwargs): ...
def construct_link_constraint(*args, **kwargs): ...
9 changes: 9 additions & 0 deletions moveit_py/moveit/core/planning_interface.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class MotionPlanResponse:
def __init__(self, *args, **kwargs) -> None: ...
def __bool__(self) -> bool: ...
@property
def error_code(self): ...
@property
def planning_time(self): ...
@property
def trajectory(self): ...
35 changes: 35 additions & 0 deletions moveit_py/moveit/core/planning_scene.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from _typeshed import Incomplete

class PlanningScene:
current_state: Incomplete
name: Incomplete
def __init__(self, *args, **kwargs) -> None: ...
def apply_collision_object(self, *args, **kwargs): ...
def check_collision(self, *args, **kwargs): ...
def check_collision_unpadded(self, *args, **kwargs): ...
def check_self_collision(self, *args, **kwargs): ...
def get_frame_transform(self, *args, **kwargs): ...
def is_path_valid(self, *args, **kwargs): ...
def is_state_colliding(self, *args, **kwargs): ...
def is_state_constrained(self, *args, **kwargs): ...
def is_state_valid(self, *args, **kwargs): ...
def knows_frame_transform(self, *args, **kwargs): ...
def load_geometry_from_file(self, *args, **kwargs): ...
def process_attached_collision_object(self, *args, **kwargs): ...
def process_octomap(self, *args, **kwargs): ...
def process_planning_scene_world(self, *args, **kwargs): ...
def remove_all_collision_objects(self, *args, **kwargs): ...
def save_geometry_to_file(self, *args, **kwargs): ...
def set_object_color(self, *args, **kwargs): ...
def __copy__(self): ...
def __deepcopy__(self): ...
@property
def allowed_collision_matrix(self): ...
@property
def planning_frame(self): ...
@property
def planning_scene_message(self): ...
@property
def robot_model(self): ...
@property
def transforms(self): ...
Loading
Loading