Skip to content

Commit 48c7850

Browse files
authored
Implement managed nodes (#865)
Signed-off-by: Ivan Santiago Paunovic <[email protected]>
1 parent 3f35f73 commit 48c7850

File tree

13 files changed

+1291
-46
lines changed

13 files changed

+1291
-46
lines changed

rclpy/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ endif()
1616

1717
find_package(ament_cmake REQUIRED)
1818
find_package(ament_cmake_python REQUIRED)
19+
find_package(lifecycle_msgs REQUIRED)
1920
find_package(rcl REQUIRED)
20-
find_package(rcl_logging_interface REQUIRED)
2121
find_package(rcl_action REQUIRED)
22+
find_package(rcl_lifecycle REQUIRED)
23+
find_package(rcl_logging_interface REQUIRED)
2224
find_package(rcl_yaml_param_parser REQUIRED)
2325
find_package(rcpputils REQUIRED)
2426
find_package(rcutils REQUIRED)
@@ -113,6 +115,7 @@ pybind11_add_module(_rclpy_pybind11 SHARED
113115
src/rclpy/exceptions.cpp
114116
src/rclpy/graph.cpp
115117
src/rclpy/guard_condition.cpp
118+
src/rclpy/lifecycle.cpp
116119
src/rclpy/logging.cpp
117120
src/rclpy/names.cpp
118121
src/rclpy/node.cpp
@@ -133,8 +136,11 @@ target_include_directories(_rclpy_pybind11 PRIVATE
133136
src/rclpy/
134137
)
135138
target_link_libraries(_rclpy_pybind11 PRIVATE
139+
lifecycle_msgs::lifecycle_msgs__rosidl_generator_c
140+
lifecycle_msgs::lifecycle_msgs__rosidl_typesupport_c
136141
rcl::rcl
137142
rcl_action::rcl_action
143+
rcl_lifecycle::rcl_lifecycle
138144
rcl_logging_interface::rcl_logging_interface
139145
rcpputils::rcpputils
140146
rcutils::rcutils

rclpy/package.xml

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

2626
<depend>rmw_implementation</depend>
2727
<depend>rcl</depend>
28+
<depend>rcl_lifecycle</depend>
2829
<depend>rcl_logging_interface</depend>
2930
<depend>rcl_action</depend>
3031
<depend>rcl_yaml_param_parser</depend>

rclpy/rclpy/lifecycle/__init__.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright 2021 Open Source Robotics Foundation, Inc.
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 .managed_entity import ManagedEntity
16+
from .managed_entity import SimpleManagedEntity
17+
from .node import LifecycleNode
18+
from .node import LifecycleNodeMixin
19+
from .node import LifecycleState
20+
from .publisher import LifecyclePublisher
21+
22+
from ..impl.implementation_singleton import rclpy_implementation as _rclpy
23+
24+
# reexport LifecycleNode as Node, so it's possible to write:
25+
# from rclpy.lifecycle import Node
26+
# Do not include that in __all__ to avoid mixing it up with rclpy.node.Node.
27+
Node = LifecycleNode
28+
# same idea here
29+
NodeMixin = LifecycleNodeMixin
30+
State = LifecycleState
31+
Publisher = LifecyclePublisher
32+
33+
# enum defined in pybind11 plugin
34+
TransitionCallbackReturn = _rclpy.TransitionCallbackReturnType
35+
36+
37+
__all__ = [
38+
'LifecycleNodeMixin',
39+
'LifecycleNode',
40+
'LifecycleState',
41+
'LifecyclePublisher',
42+
'ManagedEntity',
43+
'SimpleManagedEntity',
44+
]
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Copyright 2021 Open Source Robotics Foundation, Inc.
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 functools import wraps
16+
17+
from ..impl.implementation_singleton import rclpy_implementation as _rclpy
18+
19+
20+
TransitionCallbackReturn = _rclpy.TransitionCallbackReturnType
21+
22+
23+
class ManagedEntity:
24+
25+
def on_configure(self, state) -> TransitionCallbackReturn:
26+
"""Handle configure transition request."""
27+
return TransitionCallbackReturn.SUCCESS
28+
29+
def on_cleanup(self, state) -> TransitionCallbackReturn:
30+
"""Handle cleanup transition request."""
31+
return TransitionCallbackReturn.SUCCESS
32+
33+
def on_shutdown(self, state) -> TransitionCallbackReturn:
34+
"""Handle shutdown transition request."""
35+
return TransitionCallbackReturn.SUCCESS
36+
37+
def on_activate(self, state) -> TransitionCallbackReturn:
38+
"""Handle activate transition request."""
39+
return TransitionCallbackReturn.SUCCESS
40+
41+
def on_deactivate(self, state) -> TransitionCallbackReturn:
42+
"""Handle deactivate transition request."""
43+
return TransitionCallbackReturn.SUCCESS
44+
45+
def on_error(self, state) -> TransitionCallbackReturn:
46+
"""Handle error transition request."""
47+
return TransitionCallbackReturn.SUCCESS
48+
49+
50+
class SimpleManagedEntity(ManagedEntity):
51+
"""A simple managed entity that only sets a flag when activated/deactivated."""
52+
53+
def __init__(self):
54+
self._enabled = False
55+
56+
def on_activate(self, state) -> TransitionCallbackReturn:
57+
self._enabled = True
58+
return TransitionCallbackReturn.SUCCESS
59+
60+
def on_deactivate(self, state) -> TransitionCallbackReturn:
61+
self._enabled = False
62+
return TransitionCallbackReturn.SUCCESS
63+
64+
@property
65+
def is_activated(self):
66+
return self._enabled
67+
68+
@staticmethod
69+
def when_enabled(wrapped=None, *, when_not_enabled=None):
70+
def decorator(wrapped):
71+
@wraps(wrapped)
72+
def only_when_enabled_wrapper(self: SimpleManagedEntity, *args, **kwargs):
73+
if not self._enabled:
74+
if when_not_enabled is not None:
75+
when_not_enabled()
76+
return
77+
wrapped(self, *args, **kwargs)
78+
return only_when_enabled_wrapper
79+
if wrapped is None:
80+
return decorator
81+
return decorator(wrapped)

0 commit comments

Comments
 (0)