Creating Python Service in ROS2
Step 1: Create the service (.srv) file, namely ServiceName.srv, inside an “srv” folder.
Step 2: Modify setup.py.
Step 3: Modify package.xml.
Step 4: Write the service_server node in the package subfolder inside the package folder.
There are two ways to write a service_server node in Python: 1) old-school approach, and 2) member-function approach. The following is the examples of each approach, taken from here: https://github.com/ros2/examples/tree/foxy/rclpy/services/minimal_service
Old-school approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
from example_interfaces.srv import AddTwoInts import rclpy g_node = None def add_two_ints_callback(request, response): global g_node response.sum = request.a + request.b g_node.get_logger().info( 'Incoming request\na: %d b: %d' % (request.a, request.b)) return response def main(args=None): global g_node rclpy.init(args=args) g_node = rclpy.create_node('minimal_service') srv = g_node.create_service(AddTwoInts, 'add_two_ints', add_two_ints_callback) while rclpy.ok(): rclpy.spin_once(g_node) # Destroy the service attached to the node explicitly # (optional - otherwise it will be done automatically # when the garbage collector destroys the node object) g_node.destroy_service(srv) rclpy.shutdown() if __name__ == '__main__': main() |
Member-function approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
from example_interfaces.srv import AddTwoInts import rclpy from rclpy.node import Node class MinimalService(Node): def __init__(self): super().__init__('minimal_service') self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback) def add_two_ints_callback(self, request, response): response.sum = request.a + request.b self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b)) return response def main(args=None): rclpy.init(args=args) minimal_service = MinimalService() rclpy.spin(minimal_service) rclpy.shutdown() if __name__ == '__main__': main() |
Step 5: Write the service_client node in the package subfolder inside the package folder. The following is an example using the member-function approach, taken from here: https://github.com/ros2/examples/tree/foxy/rclpy/services/minimal_client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
import sys from example_interfaces.srv import AddTwoInts import rclpy from rclpy.node import Node class MinimalClientAsync(Node): def __init__(self): super().__init__('minimal_client_async') self.cli = self.create_client(AddTwoInts, 'add_two_ints') while not self.cli.wait_for_service(timeout_sec=1.0): self.get_logger().info('service not available, waiting again...') self.req = AddTwoInts.Request() def send_request(self): self.req.a = int(sys.argv[1]) self.req.b = int(sys.argv[2]) self.future = self.cli.call_async(self.req) def main(args=None): rclpy.init(args=args) minimal_client = MinimalClientAsync() minimal_client.send_request() while rclpy.ok(): rclpy.spin_once(minimal_client) if minimal_client.future.done(): try: response = minimal_client.future.result() except Exception as e: minimal_client.get_logger().info( 'Service call failed %r' % (e,)) else: minimal_client.get_logger().info( 'Result of add_two_ints: for %d + %d = %d' % (minimal_client.req.a, minimal_client.req.b, response.sum)) break minimal_client.destroy_node() rclpy.shutdown() if __name__ == '__main__': main() |
Step 6: Build the package by using the “colcon build” command.