Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 32 additions & 10 deletions rclpy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,16 @@ find_package(rosidl_runtime_c REQUIRED)
cmake_policy(SET CMP0094 NEW)
set(Python3_FIND_UNVERSIONED_NAMES FIRST)

# Find python before pybind11
# Find python before nanobind
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)

find_package(pybind11 REQUIRED)
# nanobind's CMake config requires the new-style FindPython module with the
# Python::Module target defined. Reuse the interpreter found above so both
# find_package calls agree on the same Python installation.
set(Python_EXECUTABLE "${Python3_EXECUTABLE}")
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)

find_package(nanobind REQUIRED)

# enables using the Python extensions from the build space for testing
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_rclpy/__init__.py" "")
Expand Down Expand Up @@ -69,10 +75,10 @@ function(configure_build_install_location _library_name)
)
endfunction()

# Split from main extension and converted to pybind11
pybind11_add_module(_rclpy_pybind11
# Split from main extension and converted to nanobind
nanobind_add_module(_rclpy_nanobind
src/rclpy/_rclpy_logging.cpp
src/rclpy/_rclpy_pybind11.cpp
src/rclpy/_rclpy_nanobind.cpp
src/rclpy/action_client.cpp
src/rclpy/action_goal_handle.cpp
src/rclpy/action_server.cpp
Expand Down Expand Up @@ -111,13 +117,13 @@ pybind11_add_module(_rclpy_pybind11
)

if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT APPLE)
target_link_libraries(_rclpy_pybind11 PRIVATE atomic)
target_link_libraries(_rclpy_nanobind PRIVATE atomic)
endif()

target_include_directories(_rclpy_pybind11 PRIVATE
target_include_directories(_rclpy_nanobind PRIVATE
src/rclpy/
)
target_link_libraries(_rclpy_pybind11 PRIVATE
target_link_libraries(_rclpy_nanobind PRIVATE
ament_cmake_ros_core::ament_ros_cxx_standard
lifecycle_msgs::lifecycle_msgs__rosidl_generator_c
lifecycle_msgs::lifecycle_msgs__rosidl_typesupport_c
Expand All @@ -130,7 +136,23 @@ target_link_libraries(_rclpy_pybind11 PRIVATE
rcutils::rcutils
rosidl_runtime_c::rosidl_runtime_c
)
configure_build_install_location(_rclpy_pybind11)
configure_build_install_location(_rclpy_nanobind)

# Generate the type stubs for the extension module into the source tree,
# so that they stay committed alongside the bindings.
nanobind_add_stub(_rclpy_nanobind_stub
MODULE _rclpy_nanobind
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/rclpy/impl/_rclpy_nanobind.pyi"
PYTHON_PATH "${CMAKE_CURRENT_BINARY_DIR}/test_rclpy"
PATTERN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/stubgen_pattern.pat"
DEPENDS _rclpy_nanobind "${CMAKE_CURRENT_SOURCE_DIR}/stubgen_pattern.pat"
)
nanobind_add_stub(_rclpy_nanobind_service_introspection_stub
MODULE _rclpy_nanobind.service_introspection
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/rclpy/impl/service_introspection.pyi"
PYTHON_PATH "${CMAKE_CURRENT_BINARY_DIR}/test_rclpy"
DEPENDS _rclpy_nanobind
)

if(NOT WIN32)
ament_environment_hooks(
Expand Down Expand Up @@ -175,7 +197,7 @@ if(BUILD_TESTING)
target_include_directories(test_python_allocator PRIVATE src/rclpy)
target_link_libraries(test_python_allocator
ament_cmake_ros_core::ament_ros_cxx_standard
pybind11::embed)
Python3::Python)

if(NOT _typesupport_impls STREQUAL "")
# Run each test in its own pytest invocation to isolate any global state in rclpy
Expand Down
2 changes: 1 addition & 1 deletion rclpy/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<build_depend>rcl_lifecycle</build_depend>
<build_depend>rcl_logging_interface</build_depend>
<build_depend>rcl_yaml_param_parser</build_depend>
<build_depend>pybind11-dev</build_depend>
<build_depend>nanobind-dev</build_depend>
<build_depend>python3-dev</build_depend>
<build_depend>rcpputils</build_depend>
<build_depend>rcutils</build_depend>
Expand Down
2 changes: 1 addition & 1 deletion rclpy/rclpy/duration.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(self, *, seconds: Union[int, float] = 0, nanoseconds: Union[int, fl
total_nanoseconds = int(seconds * S_TO_NS)
total_nanoseconds += int(nanoseconds)
if total_nanoseconds >= 2**63 or total_nanoseconds < -2**63:
# pybind11 would raise TypeError, but we want OverflowError
# nanobind would raise TypeError, but we want OverflowError
raise OverflowError(
'Total nanoseconds value is too large to store in C duration.')
self._duration_handle = _rclpy.rcl_duration_t(total_nanoseconds)
Expand Down
15 changes: 3 additions & 12 deletions rclpy/rclpy/experimental/events_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,6 @@ def EventsExecutor(*, context: typing.Optional[rclpy.Context] = None) -> rclpy.e
# Python backtrace dumped with the crash.
faulthandler.enable()

ex = typing.cast(rclpy.executors.Executor, _rclpy.EventsExecutor(context))

# rclpy.Executor does this too. Note, the context itself is smart enough to check
# for bound methods, and check whether the instances they're bound to still exist at
# callback time, so we don't have to worry about tearing down this stale callback at
# destruction time.
# TODO(bmartin427) This should really be done inside of the EventsExecutor
# implementation itself, but I'm unable to figure out a pybind11 incantation that
# allows me to pass this bound method call from C++.
context.on_shutdown(ex.wake)

return ex
# Note the EventsExecutor implementation takes care of registering a wake-on-shutdown
# callback with the context.
return typing.cast(rclpy.executors.Executor, _rclpy.EventsExecutor(context))
Loading