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
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
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
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.
.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 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 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
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
Now, we’re 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, 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
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_wssource ./devel/setup.bash
After that, we run the server
node:
rosrun edu_server_client add_two_ints_server
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_wssource ./devel/setup.bash
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
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)
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