Writing a Service Client (C++)

Create a package

First of all, you will have to create a new package, where you will place the code for your Publisher node. For this, you need to be in your ROS2 workspace src folder.

cd ~/ros2_ws/src

Now, execute the following command to create the package:

ros2 pkg create --build-type ament_cmake service_client_cpp --dependencies rclcpp example_interfaces

You will get an output similar to this one:

This will automatically generate your package and all its necessary files and folders. Now, navigate to the ros2_ws/src folder in order to create your file.

Write the code

Inside the ros2_ws/src folder, create a new file named service_client.cpp. Into this file, you will copy the following code

#include <inttypes.h>
#include <memory>
#include "example_interfaces/srv/add_two_ints.hpp"
#include "rclcpp/rclcpp.hpp"

using AddTwoInts = example_interfaces::srv::AddTwoInts;
rclcpp::Node::SharedPtr g_node = nullptr;

void handle_service(
const std::shared_ptr<rmw_request_id_t> request_header,
const std::shared_ptr<AddTwoInts::Request> request,
const std::shared_ptr<AddTwoInts::Response> response)
{
(void)request_header;
RCLCPP_INFO(
g_node->get_logger(),
"request: %" PRId64 " + %" PRId64, request->a, request->b);
response->sum = request->a + request->b;
}

int main(int argc, char ** argv)
{
rclcpp::init(argc, argv);
g_node = rclcpp::Node::make_shared("minimal_service");
auto server = g_node->create_service<AddTwoInts>("add_two_ints", handle_service);
rclcpp::spin(g_node);
rclcpp::shutdown();
g_node = nullptr;
return 0;
}

Review the code

Similar to the service server node, the following lines of code create the node and then create the client for that node:

std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("add_two_ints_client");
rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client =
node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints");

Next, the request is created. Its structure is defined by the .srv file mentioned earlier.

auto request = std::make_shared<example_interfaces::srv::AddTwoInts::Request>();
request->a = atoll(argv[1]);
request->b = atoll(argv[2]);

The while loop gives the client 1 second to search for service nodes in the network. If it can’t find any, it will continue waiting.

RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");

If the client is canceled (e.g. by you entering Ctrl+C into the terminal), it will return an error log message stating it was interrupted.

RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");
return 0;

Then the client sends its request, and the node spins until it receives its response, or fails.

Modify the CMakeLists.txt file

In the Build section of your CMakeLists.txt file, add the following lines to your CMakeLists.txt file, right above the ament_package() line.

add_executable(service_client_node src/service_client.cpp)
ament_target_dependencies(service_client_node rclcpp example_interfaces)

install(TARGETS
service_client_node
DESTINATION lib/${PROJECT_NAME}
)

Compile the package

First of all, let's go the ros2_ws folder in order to be able to compile.

cd ~/ros2_ws;

Let's now execute the colcon command in order to build our node.

colcon build --symlink-install

You will get an output like the following one:

Finally, let's source the workspace.

source ~/ros2_ws/install/setup.bash

Testing the Service Client

First of all, we need to run our service server (so that it becomes available) with the following command:

ros2 run service_server_cpp service_server_node

Now let's run our client node with the following command:

ros2 run service_client_cpp service_client_node 2 3

From the Shell where you executed the Server, you will get the following:

And from the Shell where you called the Server, you wll get the following:

Practice Online

Also, you can test this tutorial in ROSDS, using a ROSject which already contains all the code described in it. You can get the ROSject by clicking on the button below:

Above: Get ROSDS ROSject

The link above will take yo a page like the below one:

Now, you just need to Sign In (or Sign Up if you don't have an account yet) to ROSDS in order to launch the ROSject.