Skip to content

Commit 039907a

Browse files
author
Brad Martin
committed
Introduce EventsExecutor implementation (#1389)
1 parent ba72a01 commit 039907a

File tree

14 files changed

+2494
-0
lines changed

14 files changed

+2494
-0
lines changed

rclpy/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ endif()
1717

1818
find_package(ament_cmake REQUIRED)
1919
find_package(ament_cmake_python REQUIRED)
20+
find_package(Boost REQUIRED)
2021
find_package(lifecycle_msgs REQUIRED)
2122
find_package(rcl REQUIRED)
2223
find_package(rcl_action REQUIRED)
@@ -90,6 +91,9 @@ pybind11_add_module(_rclpy_pybind11 SHARED
9091
src/rclpy/destroyable.cpp
9192
src/rclpy/duration.cpp
9293
src/rclpy/clock_event.cpp
94+
src/rclpy/events_executor/events_executor.cpp
95+
src/rclpy/events_executor/rcl_support.cpp
96+
src/rclpy/events_executor/timers_manager.cpp
9397
src/rclpy/exceptions.cpp
9498
src/rclpy/graph.cpp
9599
src/rclpy/guard_condition.cpp
@@ -121,6 +125,7 @@ target_include_directories(_rclpy_pybind11 PRIVATE
121125
src/rclpy/
122126
)
123127
target_link_libraries(_rclpy_pybind11 PRIVATE
128+
Boost::boost
124129
lifecycle_msgs::lifecycle_msgs__rosidl_generator_c
125130
lifecycle_msgs::lifecycle_msgs__rosidl_typesupport_c
126131
rcl::rcl
@@ -182,6 +187,7 @@ if(BUILD_TESTING)
182187
test/test_create_node.py
183188
test/test_create_while_spinning.py
184189
test/test_destruction.py
190+
test/test_events_executor.py
185191
test/test_executor.py
186192
test/test_expand_topic_name.py
187193
test/test_guard_condition.py

rclpy/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
<buildtool_depend>ament_cmake</buildtool_depend>
1919

20+
<build_depend>boost</build_depend>
2021
<build_depend>pybind11_vendor</build_depend>
2122
<build_depend>python3-dev</build_depend>
2223
<build_depend>rcpputils</build_depend>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2024 Brad Martin
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from .events_executor import EventsExecutor
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright 2024 Brad Martin
2+
# Copyright 2024 Merlin Labs, Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
import faulthandler
16+
import typing
17+
18+
import rclpy.executors
19+
import rclpy.node
20+
from rclpy.impl.implementation_singleton import rclpy_implementation as _rclpy
21+
22+
23+
# Try to look like we inherit from the rclpy Executor for type checking purposes without
24+
# getting any of the code from the base class.
25+
def EventsExecutor(*, context: rclpy.Context | None = None) -> rclpy.executors.Executor:
26+
if context is None:
27+
context = rclpy.get_default_context()
28+
29+
# For debugging purposes, if anything goes wrong in C++ make sure we also get a
30+
# Python backtrace dumped with the crash.
31+
faulthandler.enable()
32+
33+
ex = typing.cast(rclpy.executors.Executor, _rclpy.EventsExecutor(context))
34+
35+
# rclpy.Executor does this too. Note, the context itself is smart enough to check
36+
# for bound methods, and check whether the instances they're bound to still exist at
37+
# callback time, so we don't have to worry about tearing down this stale callback at
38+
# destruction time.
39+
# TODO(bmartin427) This should really be done inside of the EventsExecutor
40+
# implementation itself, but I'm unable to figure out a pybind11 incantation that
41+
# allows me to pass this bound method call from C++.
42+
context.on_shutdown(ex.wake)
43+
44+
return ex

rclpy/src/rclpy/_rclpy_pybind11.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "duration.hpp"
3333
#include "clock_event.hpp"
3434
#include "event_handle.hpp"
35+
#include "events_executor/events_executor.hpp"
3536
#include "exceptions.hpp"
3637
#include "graph.hpp"
3738
#include "guard_condition.hpp"
@@ -247,4 +248,6 @@ PYBIND11_MODULE(_rclpy_pybind11, m) {
247248
rclpy::define_signal_handler_api(m);
248249
rclpy::define_clock_event(m);
249250
rclpy::define_lifecycle_api(m);
251+
252+
rclpy::events_executor::define_events_executor(m);
250253
}

0 commit comments

Comments
 (0)