How to write a simple service and client in ROS in C++

In robotics, the Robot Operating System (ROS) is an open-source framework for building robotic applications. It provides a collection of software libraries and tools to help developers create complex and robust robot behavior across various robotic platforms. ROS offers capabilities such as hardware abstraction, device control, message-passing between processes, and package management, making it an essential resource for robotics research and development. A fundamental aspect of ROS is its use of a service-client architecture, which allows for discrete segments of a robot's operation to be compartmentalized and interact seamlessly.

In this Answer, we'll explore the practical aspects of ROS by demonstrating how to write a simple service and client in ROS using C++. We'll be writing a server that returns the sum of two integers whenever a client sends a request (with two integers as parameters). We'll look into how to work with a catkin workspace, create a ROS package, and run different ROS nodes. To get started, we need to install ROS. We can do that by following the instructions on the ROS Installation pagehttps://wiki.ros.org/ROS/Installation. On our platform, we've installed ROS Noetic.

ROS server-client protocol
ROS server-client protocol

Creating a ROS Package

A ROS package is a fundamental organizational unit used to structure and manage the robotic software. It’s a directory that contains code, data, and configuration files related to a specific functionality, module, or component of a robotic system. Packages help us keep our code modular, organized, and easily shareable among the ROS community.

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

cd ~/catkin_ws/src
Command to change directory

Now, we utilize the catkin_create_pkg script to generate a new package. To use it, we need to provide a package name, and we can optionally specify a list of dependencies that the package relies on. Here’s the command we use to create a package named edu_server_client specifying its dependencies as roscpp.

catkin_create_pkg edu_server_client roscpp
Command to create package

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

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 package.xml to make sure that the .srv files are turned into source code for the respective programming language, C++ in our case. We've made these changes on lines 40 and 46 in the package.xml file, which tells us that we need message_generation at build time and message_runtime at runtime.

Building the catkin workspace

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

Let's first change our directory to the catkin workspace:

cd ~/catkin_ws
Command to change directory

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

Note: On the Educative platform, 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’re all set to build our catkin workspace. Execute the following command in the terminal:

catkin_make
Command to build the catkin 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.

Running the nodes

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

roscore

It’s 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 the service can be viewed in the server.cpp file in the widget below. Here's a line-by-line explanation:

  • Line 1: ros/ros.h is a convenient header inclusion that incorporates all the necessary headers for utilizing the widely used public components of the ROS system.

  • Line 2: edu_server_client/AddTwoInts.h is the header file generated from the .srv file.

  • Line 4–5: This function adds two integers. It accepts the request and response types specified in the service (.srv) file and returns a boolean value.

  • Line 7: This adds two integers and stores the response.

  • Line 8–9: This logs information about the request and response.

  • Line 10: The service returns true when it is complete.

  • Line 18: This creates the service and advertises over ROS.

To run the server, we open a new terminal using the "+" button. We change the directory to the catkin workspace and source the workspace's setup.*sh file using the following commands:

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

After that, we run the server node:

rosrun edu_server_client add_two_ints_server
Command to run server node

Client

The code for the subscriber is given in the client.cpp file. Here's a line-by-line explanation:

  • Line 15: This creates a client for the add_two_ints service. Later, we use the ros::ServiceClient object to call the service.

  • Line 16–18: This instantiates the AddTwoInts service class, and assigns values to its request member.

  • Line 19: This invokes the service, and since service calls operate in a blocking manner, it returns after the call is completed. If the service call is successful, the call() function returns true, and srv.response contains valid data. If the call is unsuccessful, the call() function returns false, and srv.response contains invalid data.

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

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

The last step is to run the client node. Here, 16 and 9 are the two integers we want to add.

rosrun edu_server_client add_two_ints_client 16 9
Command to run client node

Playground

As mentioned earlier, we'll practice 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 roscpp std_msgs 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})

add_executable(add_two_ints_server src/server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server edu_server_client_gencpp)

add_executable(add_two_ints_client src/client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client edu_server_client_gencpp)
A simple service and client implementation in ROS in C++

Conclusion

Creating a ROS package and building different nodes under that package facilitate the development of a robust robotic system, where each node executes distinct tasks, which in turn enhances the overall system throughput and efficiency.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved