Skip to content

Commit

Permalink
Introduce EventsExecutor implementation (ros2#1389)
Browse files Browse the repository at this point in the history
Signed-off-by: Brad Martin <[email protected]>
  • Loading branch information
Brad Martin committed Jan 4, 2025
1 parent ba72a01 commit 45f7f5f
Show file tree
Hide file tree
Showing 14 changed files with 2,494 additions and 0 deletions.
6 changes: 6 additions & 0 deletions rclpy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ endif()

find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)
find_package(Boost REQUIRED)
find_package(lifecycle_msgs REQUIRED)
find_package(rcl REQUIRED)
find_package(rcl_action REQUIRED)
Expand Down Expand Up @@ -90,6 +91,9 @@ pybind11_add_module(_rclpy_pybind11 SHARED
src/rclpy/destroyable.cpp
src/rclpy/duration.cpp
src/rclpy/clock_event.cpp
src/rclpy/events_executor/events_executor.cpp
src/rclpy/events_executor/rcl_support.cpp
src/rclpy/events_executor/timers_manager.cpp
src/rclpy/exceptions.cpp
src/rclpy/graph.cpp
src/rclpy/guard_condition.cpp
Expand Down Expand Up @@ -121,6 +125,7 @@ target_include_directories(_rclpy_pybind11 PRIVATE
src/rclpy/
)
target_link_libraries(_rclpy_pybind11 PRIVATE
Boost::boost
lifecycle_msgs::lifecycle_msgs__rosidl_generator_c
lifecycle_msgs::lifecycle_msgs__rosidl_typesupport_c
rcl::rcl
Expand Down Expand Up @@ -182,6 +187,7 @@ if(BUILD_TESTING)
test/test_create_node.py
test/test_create_while_spinning.py
test/test_destruction.py
test/test_events_executor.py
test/test_executor.py
test/test_expand_topic_name.py
test/test_guard_condition.py
Expand Down
1 change: 1 addition & 0 deletions rclpy/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

<buildtool_depend>ament_cmake</buildtool_depend>

<build_depend>boost</build_depend>
<build_depend>pybind11_vendor</build_depend>
<build_depend>python3-dev</build_depend>
<build_depend>rcpputils</build_depend>
Expand Down
15 changes: 15 additions & 0 deletions rclpy/rclpy/experimental/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2024 Brad Martin
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .events_executor import EventsExecutor
44 changes: 44 additions & 0 deletions rclpy/rclpy/experimental/events_executor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright 2024 Brad Martin
# Copyright 2024 Merlin Labs, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import faulthandler
import typing

import rclpy.executors
import rclpy.node
from rclpy.impl.implementation_singleton import rclpy_implementation as _rclpy


# Try to look like we inherit from the rclpy Executor for type checking purposes without
# getting any of the code from the base class.
def EventsExecutor(*, context: rclpy.Context | None = None) -> rclpy.executors.Executor:
if context is None:
context = rclpy.get_default_context()

# For debugging purposes, if anything goes wrong in C++ make sure we also get a
# 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
3 changes: 3 additions & 0 deletions rclpy/src/rclpy/_rclpy_pybind11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "duration.hpp"
#include "clock_event.hpp"
#include "event_handle.hpp"
#include "events_executor/events_executor.hpp"
#include "exceptions.hpp"
#include "graph.hpp"
#include "guard_condition.hpp"
Expand Down Expand Up @@ -247,4 +248,6 @@ PYBIND11_MODULE(_rclpy_pybind11, m) {
rclpy::define_signal_handler_api(m);
rclpy::define_clock_event(m);
rclpy::define_lifecycle_api(m);

rclpy::events_executor::define_events_executor(m);
}
Loading

0 comments on commit 45f7f5f

Please sign in to comment.