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:
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:
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
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.
