From bf62d7791740398d7a6a69b06e6e877cc00f0821 Mon Sep 17 00:00:00 2001 From: Tomoya Fujita Date: Thu, 27 Mar 2025 15:27:38 -0700 Subject: [PATCH 1/2] add publisher_member_function_with_wait_for_all_acked.py. (#407) Signed-off-by: Tomoya.Fujita (cherry picked from commit bea0186806239ed2e28958b62b6eacab3390e8d0) --- rclpy/topics/minimal_publisher/README.md | 1 + ...member_function_with_wait_for_all_acked.py | 69 +++++++++++++++++++ rclpy/topics/minimal_publisher/setup.py | 2 + 3 files changed, 72 insertions(+) create mode 100644 rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function_with_wait_for_all_acked.py diff --git a/rclpy/topics/minimal_publisher/README.md b/rclpy/topics/minimal_publisher/README.md index fc9d22afd..8909109db 100644 --- a/rclpy/topics/minimal_publisher/README.md +++ b/rclpy/topics/minimal_publisher/README.md @@ -4,3 +4,4 @@ This package contains a few different strategies for creating short nodes that b The `publisher_old_school` recipe creates a talker node very similar to how it would be done in ROS 1 using rospy. The `publisher_local_function` recipe shows how to leverage the timers provided by ROS 2 to trigger message publication. The `publisher_member_function` recipe creates a class MinimalPublisher that sends messages periodically. +The `publisher_member_function_with_wait_for_all_acked` recipe creates a class MinimalPublisher that sends messages and wait for all messages are acknowledged. diff --git a/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function_with_wait_for_all_acked.py b/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function_with_wait_for_all_acked.py new file mode 100644 index 000000000..e6aed9832 --- /dev/null +++ b/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function_with_wait_for_all_acked.py @@ -0,0 +1,69 @@ +# Copyright 2025 Sony Group Corporation. +# +# 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 rclpy +from rclpy.duration import Duration +from rclpy.executors import ExternalShutdownException +from rclpy.node import Node + +from std_msgs.msg import String + + +class MinimalPublisher(Node): + + def __init__(self): + super().__init__('minimal_publisher_with_wait_for_all_acked') + reliable_qos = rclpy.qos.QoSProfile( + depth=10, + reliability=rclpy.qos.QoSReliabilityPolicy.RELIABLE) + self.publisher_ = self.create_publisher(String, 'topic', reliable_qos) + + self.timer_period = 0.5 # seconds + self.timer = self.create_timer(self.timer_period, self.timer_callback) + self.i = 0 + self.max_count = 10 + + def wait_for_all_acked(self): + self.get_logger().info('Waiting for all messages to be acknowledged...') + acknowledged = self.publisher_.wait_for_all_acked(Duration(seconds=3)) + if acknowledged: + self.get_logger().info('All messages acknowledged.') + else: + self.get_logger().warn('Not all messages were acknowledged.') + + def timer_callback(self): + if self.i < self.max_count: + msg = String() + msg.data = 'Hello World: %d' % self.i + self.publisher_.publish(msg) + self.get_logger().info('Publishing: "%s"' % msg.data) + self.i += 1 + else: + self.timer.cancel() + self.wait_for_all_acked() + self.i = 0 + self.timer.reset() + +def main(args=None): + rclpy.init(args=args) + minimal_publisher = MinimalPublisher() + try: + rclpy.spin(minimal_publisher) + except (KeyboardInterrupt, ExternalShutdownException): + pass + finally: + rclpy.shutdown() + +if __name__ == '__main__': + main() diff --git a/rclpy/topics/minimal_publisher/setup.py b/rclpy/topics/minimal_publisher/setup.py index 509c85b01..3c877347f 100644 --- a/rclpy/topics/minimal_publisher/setup.py +++ b/rclpy/topics/minimal_publisher/setup.py @@ -34,6 +34,8 @@ ' examples_rclpy_minimal_publisher.publisher_local_function:main', 'publisher_member_function =' ' examples_rclpy_minimal_publisher.publisher_member_function:main', + 'publisher_member_function_with_wait_for_all_acked =' + ' examples_rclpy_minimal_publisher.publisher_member_function_with_wait_for_all_acked:main', ], }, ) From b5c82d7e3bad0ab6cf94f418bbc6beb82af08f8a Mon Sep 17 00:00:00 2001 From: Tomoya Fujita Date: Fri, 28 Mar 2025 04:24:39 -0700 Subject: [PATCH 2/2] address flake8 errors for examples_rclpy_minimal_publisher. (#410) Signed-off-by: Tomoya Fujita --- .../publisher_member_function_with_wait_for_all_acked.py | 2 ++ rclpy/topics/minimal_publisher/setup.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function_with_wait_for_all_acked.py b/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function_with_wait_for_all_acked.py index e6aed9832..5a77a935d 100644 --- a/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function_with_wait_for_all_acked.py +++ b/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function_with_wait_for_all_acked.py @@ -55,6 +55,7 @@ def timer_callback(self): self.i = 0 self.timer.reset() + def main(args=None): rclpy.init(args=args) minimal_publisher = MinimalPublisher() @@ -65,5 +66,6 @@ def main(args=None): finally: rclpy.shutdown() + if __name__ == '__main__': main() diff --git a/rclpy/topics/minimal_publisher/setup.py b/rclpy/topics/minimal_publisher/setup.py index 3c877347f..b69142cdf 100644 --- a/rclpy/topics/minimal_publisher/setup.py +++ b/rclpy/topics/minimal_publisher/setup.py @@ -35,7 +35,8 @@ 'publisher_member_function =' ' examples_rclpy_minimal_publisher.publisher_member_function:main', 'publisher_member_function_with_wait_for_all_acked =' - ' examples_rclpy_minimal_publisher.publisher_member_function_with_wait_for_all_acked:main', + ' examples_rclpy_minimal_publisher.' + 'publisher_member_function_with_wait_for_all_acked:main', ], }, )