How to write a simple service and client in ROS in Python

Robot Operating System (ROS) has emerged as a transformative force in robotics, providing a flexible and modular framework that streamlines the development of robotic applications. ROS facilitates seamless communication and integration between disparate robotic components, enabling the creation of sophisticated and efficient robotic systems. With its open-source nature and extensive library of prebuilt packages, ROS has become the go-to platform for researchers, engineers, and hobbyists. A fundamental aspect of ROS is its service/client architecture, which allows discrete segments of a robot’s operation to be segregated and interact seamlessly.

In this Answer, we explore the hands-on facets of ROS, illustrating the process of creating a simple service and client in ROS using Python. The focus is on writing a server that computes and returns the sum of two integers in response to a client’s request, which includes providing two integers as parameters. The Answer will guide us through the utilization of a catkin workspace, the creation of a ROS package, and the execution of distinct ROS nodes. To initiate this journey, the first step involves installing ROS, and the instructions for installation can be found on the ROS installationhttps://wiki.ros.org/ROS/Installation page. Specifically, on our platform, we have implemented ROS Noetic.

Create a ROS package

A ROS package is a fundamental organizational unit that structures and manages the robotic software. A ROS package is a directory containing code, data, and configuration files related to a robotic system’s specific functionality, module, or component. Packages help us keep our code modular, organized, and easily shareable among the ROS community. Here are some key aspects of ROS packages:

Let’s start by creating a ROS package. We’ll be building our code in the widget at the bottom. First, change to the source space directory of the catkin workspace (we created this directory while setting up ROS):

cd ~/catkin_ws/src
Command to change the directory

Now, we utilize the catkin_create_pkg script to generate a new package. To use it, we need to provide a package_name command and we can optionally specify a list of dependencies that the package relies on. Having said that, we use the following command to create package named edu_server_client, specifying its dependencies as rospy. rospy is a Python library that serves as a client library for ROS. It allows developers to write ROS nodes in Python, enabling them to interact with ROS Master, publish, and subscribe to topics, call services, and utilize other ROS functionalities.

catkin_create_pkg edu_server_client rospy
Command to create the package

As a result, we’ll find a edu_server_client directory containing a package.xml and a CMakeLists.txt that have already been partially populated with the details we provided to catkin_create_pkg.

Service (.srv) files

In ROS, .srv files (or service files) are used to define the structure of communication services between different nodes in a ROS system. Services in ROS provide a way for nodes to send requests and receive responses in a synchronous manner. Unlike topics, which involve continuous streams of data, services are used for more interactive and point-to-point communication.

A typical .srv file in ROS consists of two main parts: the request and the response. These parts define the data structures that a client can send when requesting a service and the data structure that the service returns in response.

We’ll be using the srv/AddTwoInts.srv service file for the communication between our service and client. We also need to update our packagle.xml to make sure that the .srv files are turned into source code for the respective programming language, Python in our case. We’ve done these changes in lines 40 and 46 in packagle.xml which tells us that we need message_generation at build time and message_runtime at runtime.

Build the catkin workspace

Building the catkin workspace is the process of compiling and constructing the software packages contained within a catkin workspace in ROS. A catkin workspace is a directory where ROS packages are organized, built, and maintained.

Let’s first change our directory to catkin workspace:

cd ~/catkin_ws
Command to change the directory

Before building the package, let’s copy the code to the package directory:

Note: In this Answer, all codes in the widget are kept in the usercode directory.

cp ../../usercode/edu_server_client src -r
Command to copy the code

Now, we are all set to build our catkin workspace. Execute the following command in the terminal:

catkin_make
Command to build the workspace

After the workspace has been built, we get build and devel folders in our current directory. In the devel folder, we have several setup.*sh files. Sourcing any of these files will overlay this workspace on top of our environment.

Run the nodes

We’re all set to run our ROS nodes to exhibit the publisher and subscriber behavior. Before running the nodes, make sure that roscore is up and running.

The roscore node

It is the core of the ROS ecosystem and serves as the master process that manages various essential services and functionalities required for ROS nodes to communicate and work together.

To start roscore, we can run the following command:

roscore
Command to run roscore

Service

The code for service can be viewed in server.py in the widget below.

  • Line 1: At the outset of every Python ROS node, we find this declaration which ensures that our script is executed as a Python script.

  • Line 6: Importing rospy is essential when crafting a ROS Node.

  • Lines 8–10: This function is called with instance of AddTwoIntsRequest and returns instance of AddTwoIntsResponse.

  • Line 13: We inform rospy of our node’s name, a crucial step before it can establish communication with the ROS Master. In this instance, our node will be identified as add_two_ints_server.

  • Line 14: We declare a new service, add_two_ints, with the AddTwoInts service type, and tell rospy that all requests are passed to handle_add_two_ints function.

  • Line 16: It ensures that our node remains active and doesn't exit until the node has undergone shutdown.

To run the server, open a new terminal using the “+” button. Change the directory to catkin workspace and source the workspace’s setup.*sh file using the following commands:

cd ~/catkin_ws
source ./devel/setup.bash
Source the setup file

After that, run the server node:

rosrun edu_server_client server.py
Command to run the server node

Client

The code for the subscriber is given in client.py and is explained below:

  • Line 10: This method is blocked until the service named add_two_ints is available.

  • Line 12: We create a handle, add_two_ints, for calling the service.

  • Lines 13–14: We call the handle that generates the AddTwoIntsRequest object and return the AddTwoIntsResponse object. We enclose this call in a try/except block to catch the rospy.ServiceException exception in case the call fails.

We run the client node in the similar fashion. Open a new terminal, change the directory, and source the setup file:

cd ~/catkin_ws
source ./devel/setup.bash
Source the setup file

The last setup is to run the client node:

rosrun edu_server_client client.py 16 9
Command to run the client node

where, 16 and 9 are the two integers we want to add.

Playground

Now try it in the following widget:

cmake_minimum_required(VERSION 2.8.3)
project(edu_server_client)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS std_msgs rospy message_generation)

## Add service files
add_service_files(
  FILES
  AddTwoInts.srv
)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

## Build server and client
include_directories(include ${catkin_INCLUDE_DIRS})

catkin_install_python(PROGRAMS scripts/server.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

catkin_install_python(PROGRAMS scripts/client.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
A simple service and client in ROS in Python

Conclusion

Creating a ROS package and building different nodes under that package facilitate the development of a robust robotic system, wherein each node executes distinct tasks, thereby, enhancing the overall system throughput and efficiency.

Free Resources

Copyright ©2024 Educative, Inc. All rights reserved