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
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
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
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
.
.srv)
filesIn 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.
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
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
Now, we are all set to build our catkin workspace. Execute the following command in the terminal:
catkin_make
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.
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.
roscore
nodeIt 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
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_wssource ./devel/setup.bash
After that, run the server
node:
rosrun edu_server_client server.py
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_wssource ./devel/setup.bash
The last setup is to run the client
node:
rosrun edu_server_client client.py 16 9
where, 16
and 9
are the two integers we want to add.
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} )
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