Servicios en ROS 2

Los servicios es una manera en el que los nodos se pueden comunicar. Estos permiten que se envíen solicitudes y se reciban respuestas. Los servicios siguen una estructura cliente - servidor.

La solicitud y respuesta de mensajes es realizada vía servicios, se definen por pares de mensajes: un mensaje es el que realiza una solicitud y el otro mensaje es la respuesta. Un nodo de ROS 2 ofrece un servicio bajo un nombre 'string', el cliente llamara a ese servicio realizando una solicitud.

Un nodo es un proceso en el que se realiza una computación. Son combinados entre sí y se comunican entre ellos. Por ejemplo, un nodo puede controlar un laser, otro nodo controla los motores de las ruedas, otro nodo la localización... todos estos nodos pueden formar un robot. Existe una tolerancia adicional a fallos ya que los errores son aislados.

En este tutorial se usara un ejemplo ya existente en los binarios pre compilados de ROS 2.

Puedes encontrar este ejemplo en https://github.com/ros2/examples.

Observa el contenido del paquete e intenta entender que ocurre en cada línea.

Archivo original: https://github.com/ros2/examples

#include <iostream>

#include "rclcpp/rclcpp.hpp"

#include "example_interfaces/srv/add_two_ints.hpp"

void handle_add_two_ints(
  const std::shared_ptr<rmw_request_id_t> request_header,
  const std::shared_ptr<example_interfaces::srv::AddTwoInts::Request> request,
  std::shared_ptr<example_interfaces::srv::AddTwoInts::Response> response)
{
  (void)request_header;
  std::cout << "Incoming request" << std::endl;
  std::cout << "a: " << request->a << " b: " << request->b << std::endl;
  response->sum = request->a + request->b;
}

int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);

  auto node = rclcpp::Node::make_shared("add_two_ints_server");

  node->create_service<example_interfaces::srv::AddTwoInts>("add_two_ints", handle_add_two_ints);

  rclcpp::spin(node);

  return 0;
}

Archivo original: https://github.com/ros2/examples

#include <iostream>

#include "rclcpp/rclcpp.hpp"

#include "example_interfaces/srv/add_two_ints.hpp"

example_interfaces::srv::AddTwoInts_Response::SharedPtr send_request(
  rclcpp::Node::SharedPtr node,
  rclcpp::client::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client,
  example_interfaces::srv::AddTwoInts_Request::SharedPtr request)
{
  auto result = client->async_send_request(request);
  // Wait for the result.
  if (rclcpp::spin_until_future_complete(node, result) ==
    rclcpp::executor::FutureReturnCode::SUCCESS)
  {
    return result.get();
  } else {
    return NULL;
  }
}

int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);

  auto node = rclcpp::Node::make_shared("add_two_ints_client");

  auto client = node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints");
  auto request = std::make_shared<example_interfaces::srv::AddTwoInts::Request>();
  request->a = 2;
  request->b = 3;

  auto result = send_request(node, client, request);
  if (result) {
    printf("Result of add_two_ints: %zd\n", result->sum);
  } else {
    printf("add_two_ints_client was interrupted. Exiting.\n");
  }

  return 0;
}

Para poder comprobar este servicio necesitaras dos terminales por lo menos. Recuerda ejecutar el siguiente archivo bash en todas las terminales en las que quieras usar ROS 2:

$ . ~/ros2_wp/install/setup.bash

Primero ejecuta el servidor:

$ add_two_ints_server

Es normal que no veas ninguna salida y que la terminal se quede bloqueada. Es necesario que un cliente envíe información, para ello ejecute lo siguiente en otra terminal:

$ add_two_ints_client

Este comando enviara al servidor dos valores integer. En el caso del ejemplo se envía los valores a: 2 y b: 3. El servidor mostrara en pantalla los valores que ha recibido y realizara la suma de los mismos:

Incoming request
a: 2 b: 3

El resultado de la suma sera mostrada en el cliente, que es el que originalmente solicito el resultado:

Result of add_two_ints: 5

¿Necesitas más capacidad de cómputo? Estate atento