From 71f9536fd9e16dfd955762dd42be559b03c1405d Mon Sep 17 00:00:00 2001 From: mhidalgo-bdai <144129882+mhidalgo-bdai@users.noreply.github.com> Date: Thu, 30 May 2024 11:44:30 -0300 Subject: [PATCH] Deduplicate scope node checks (#97) Signed-off-by: Michel Hidalgo --- bdai_ros2_wrappers/bdai_ros2_wrappers/action.py | 3 ++- .../bdai_ros2_wrappers/action_client.py | 3 +-- bdai_ros2_wrappers/bdai_ros2_wrappers/scope.py | 8 ++++++++ bdai_ros2_wrappers/bdai_ros2_wrappers/service.py | 3 +-- .../bdai_ros2_wrappers/subscription.py | 15 +++++---------- .../bdai_ros2_wrappers/tf_listener_wrapper.py | 5 ++--- 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/bdai_ros2_wrappers/bdai_ros2_wrappers/action.py b/bdai_ros2_wrappers/bdai_ros2_wrappers/action.py index 8d72721..b7c5631 100644 --- a/bdai_ros2_wrappers/bdai_ros2_wrappers/action.py +++ b/bdai_ros2_wrappers/bdai_ros2_wrappers/action.py @@ -358,7 +358,8 @@ def __init__(self, action_type: Type, action_name: str, node: Optional[Node] = N kwargs: other keyword arguments are forwarded to the underlying action client. See `rclpy.action.ActionClient` documentation for further reference. """ - node = node or scope.node() + if node is None: + node = scope.ensure_node() self._action_type = action_type self._action_name = action_name self._action_client = ActionClient(node, action_type, action_name, **kwargs) diff --git a/bdai_ros2_wrappers/bdai_ros2_wrappers/action_client.py b/bdai_ros2_wrappers/bdai_ros2_wrappers/action_client.py index 4b1f292..58cb408 100644 --- a/bdai_ros2_wrappers/bdai_ros2_wrappers/action_client.py +++ b/bdai_ros2_wrappers/bdai_ros2_wrappers/action_client.py @@ -27,9 +27,8 @@ def __init__( node (Optional[Node]): optional node for action client, defaults to the current process node wait_for_server (bool): Whether to wait for the server """ - node = node or scope.node() if node is None: - raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + node = scope.ensure_node() self._node = node super().__init__(self._node, action_type, action_name) if wait_for_server: diff --git a/bdai_ros2_wrappers/bdai_ros2_wrappers/scope.py b/bdai_ros2_wrappers/bdai_ros2_wrappers/scope.py index 159e8f3..adbb6d0 100644 --- a/bdai_ros2_wrappers/bdai_ros2_wrappers/scope.py +++ b/bdai_ros2_wrappers/bdai_ros2_wrappers/scope.py @@ -529,6 +529,14 @@ def node() -> typing.Optional[rclpy.node.Node]: return scope.node +def ensure_node() -> rclpy.node.Node: + """Gets a node from the current ROS 2 aware scope or fails trying""" + current_node = node() + if current_node is None: + raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + return current_node + + def tf_listener() -> typing.Optional[TFListenerWrapper]: """Gets the tf listener of the current ROS 2 aware scope, if any.""" scope = current() diff --git a/bdai_ros2_wrappers/bdai_ros2_wrappers/service.py b/bdai_ros2_wrappers/bdai_ros2_wrappers/service.py index d52a50d..fc648a6 100644 --- a/bdai_ros2_wrappers/bdai_ros2_wrappers/service.py +++ b/bdai_ros2_wrappers/bdai_ros2_wrappers/service.py @@ -40,9 +40,8 @@ class Serviced(ComposableCallable, VectorizingCallable): """ def __init__(self, service_type: Type, service_name: str, node: Optional[Node] = None, **kwargs: Any) -> None: - node = node or scope.node() if node is None: - raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + node = scope.ensure_node() self._service_type = service_type self._service_name = service_name self._client = node.create_client(service_type, service_name, **kwargs) diff --git a/bdai_ros2_wrappers/bdai_ros2_wrappers/subscription.py b/bdai_ros2_wrappers/bdai_ros2_wrappers/subscription.py index 4b783a4..afbccc9 100644 --- a/bdai_ros2_wrappers/bdai_ros2_wrappers/subscription.py +++ b/bdai_ros2_wrappers/bdai_ros2_wrappers/subscription.py @@ -45,9 +45,8 @@ def __init__( kwargs: other keyword arguments are used to create the underlying native subscription. See `rclpy.node.Node.create_subscription` documentation for further reference. """ - node = node or scope.node() if node is None: - raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + node = scope.ensure_node() self._node = node if history_length is None: history_length = 1 @@ -150,9 +149,8 @@ def wait_for_message_async( Raises: RuntimeError: if no node is available. """ - node = node or scope.node() if node is None: - raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + node = scope.ensure_node() future = Future() def callback(msg: MessageT) -> None: @@ -187,9 +185,8 @@ def wait_for_message( Returns: The message received, or None on timeout. """ - node = node or scope.node() if node is None: - raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + node = scope.ensure_node() future = wait_for_message_async(msg_type, topic_name, node=node, **kwargs) if not wait_for_future(future, timeout_sec, context=node.context): future.cancel() @@ -224,9 +221,8 @@ def wait_for_messages( See `wait_for_messages_async` documentation for a reference on additional keyword arguments. """ - node = node or scope.node() if node is None: - raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + node = scope.ensure_node() future = wait_for_messages_async(topic_names, message_types, node=node, **kwargs) if not wait_for_future(future, timeout_sec, context=node.context): future.cancel() @@ -261,9 +257,8 @@ def wait_for_messages_async( process-wide node (if any). callback_group: optional callback group for the message filter subscribers. """ - node = node or scope.node() if node is None: - raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + node = scope.ensure_node() if qos_profiles is None: qos_profiles = [None] * len(topic_names) diff --git a/bdai_ros2_wrappers/bdai_ros2_wrappers/tf_listener_wrapper.py b/bdai_ros2_wrappers/bdai_ros2_wrappers/tf_listener_wrapper.py index 1e81957..5b393a7 100644 --- a/bdai_ros2_wrappers/bdai_ros2_wrappers/tf_listener_wrapper.py +++ b/bdai_ros2_wrappers/bdai_ros2_wrappers/tf_listener_wrapper.py @@ -71,11 +71,10 @@ def __init__(self, node: Optional[Node] = None, cache_time_s: Optional[float] = node: optional node for transform listening, defaults to the current scope node. cache_time_s: optional transform buffer size, in seconds. """ - import bdai_ros2_wrappers.scope # locally to avoid circular import + import bdai_ros2_wrappers.scope as scope # locally to avoid circular import - node = node or bdai_ros2_wrappers.scope.node() if node is None: - raise ValueError("no ROS 2 node available (did you use bdai_ros2_wrapper.process.main?)") + node = scope.ensure_node() self._node = node cache_time_py = None if cache_time_s is not None: