7.1.4-Mecanismo de comunicación de ROS:

Tutorial de comunicación por temas (topics)

Introducción a la comunicación por temas

En ROS, la comunicación por temas es una de las formas fundamentales para que los nodos intercambien información. Este tutorial le guiará por el proceso de configurar la comunicación básica por temas usando tanto C++ como Python. Implementaremos un modelo simple de publicador-suscriptor en el que el publicador envía mensajes de texto a una frecuencia de 10Hz, y el suscriptor recibe e imprime estos mensajes.

J3010

1. Modelo teórico

La comunicación por temas implica tres componentes principales:

  • ROS Master: Gestiona el registro y la conexión de los nodos.
  • Talker (Publicador): Envía mensajes.
  • Listener (Suscriptor): Recibe mensajes.

El ROS Master ayuda a establecer las conexiones entre los Talkers y los Listeners. A continuación se detalla paso a paso cómo se produce la comunicación:

  • Registro del Talker: El Talker se registra ante el ROS Master, incluyendo el nombre del tema de sus mensajes.
  • Registro del Listener: El Listener se registra ante el ROS Master, especificando el tema al que desea suscribirse.
  • Coincidencia: El ROS Master empareja al Talker y al Listener basándose en el nombre del tema y envía la información de conexión necesaria.
  • Establecimiento de la conexión: El Listener solicita una conexión al Talker, y el Talker la confirma.
  • Intercambio de mensajes: Una vez conectados, el Talker comienza a enviar mensajes al Listener.

Puntos clave:

  • El ROS Master solo es necesario para establecer la conexión.
  • La comunicación continúa incluso si se apaga el ROS Master después de que la conexión esté establecida.
  • Pueden existir múltiples Talkers y Listeners y pueden iniciarse en cualquier orden.

2. Operaciones básicas de comunicación por temas (C++)

Objetivo: Crear un nodo publicador que envíe mensajes de texto a 10Hz y un nodo suscriptor que imprima los mensajes recibidos.

Pasos:

  1. Crear paquete

    bash
    cd ~/seeed_ws/src/
    catkin_create_pkg listener_and_talker roscpp rospy std_msgs
    cd ~/seeed_ws/src/listener_and_talker/src
    touch listener.cpp talker.cpp
  2. Implementación del publicador:

    talker.cpp

    cpp
    #include "ros/ros.h"
    #include "std_msgs/String.h"
    #include <sstream>
    
    int main(int argc, char *argv[]) {
        // Set locale for printing messages in the local language
        setlocale(LC_ALL, "");
        // Initialize the ROS node with a unique name
        ros::init(argc, argv, "talker");
        // Create a ROS node handle
        ros::NodeHandle nh;
        // Create a publisher object
        ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 10);
    
        std_msgs::String msg;
        std::string msg_front = "Hello Seeed";
        int count = 0;
        ros::Rate r(10); // 10Hz
    
        while (ros::ok()) {
            std::stringstream ss;
            ss << msg_front << count;
            msg.data = ss.str();
            pub.publish(msg);
            ROS_INFO("Sent message: %s", msg.data.c_str());
            r.sleep();
            count++;
        }
        return 0;
    }
  3. Implementación del suscriptor:

    listener.cpp

    cpp
    #include "ros/ros.h"
    #include "std_msgs/String.h"
    
    void doMsg(const std_msgs::String::ConstPtr& msg_p) {
        ROS_INFO("Heard: %s", msg_p->data.c_str());
    }
    
    int main(int argc, char *argv[]) {
        setlocale(LC_ALL, "");
        ros::init(argc, argv, "listener");
        ros::NodeHandle nh;
        ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter", 10, doMsg);
        ros::spin();
        return 0;
    }
  4. Configuración de CMakeLists.txt:

    Añada el siguiente código al final del CMakeLists.txt de su paquete:

    cmake
    add_executable(listener src/listener.cpp)
    add_executable(talker src/talker.cpp)
    
    target_link_libraries(listener ${catkin_LIBRARIES})
    target_link_libraries(talker ${catkin_LIBRARIES})

    J3010

  5. Ejecución del código:

  • Abra una terminal e inicie roscore:

    bash
    roscore
  • En una nueva terminal, navegue a su espacio de trabajo y ejecute el nodo publicador:

    bash
    rosrun listener_and_talker listener
  • En otra terminal, ejecute el nodo suscriptor:

    bash
    rosrun listener_and_talker talker

    J3010

    J3010

Debería ver mensajes que se publican y se reciben, mostrados en la terminal.

3. Operaciones básicas de comunicación por temas (Python)

Objetivo: Crear un nodo publicador que envíe mensajes de texto a 10Hz y un nodo suscriptor que imprima los mensajes recibidos.

Pasos:

  1. Crear paquete

    bash
    cd ~/seeed_ws/src/
    catkin_create_pkg listener_and_talker roscpp rospy std_msgs
    mkdir ~/seeed_ws/src/listener_and_talker/script
    cd ~/seeed_ws/src/listener_and_talker/script
    touch listener.py talker.py
  2. Implementación del publicador:

    talker.py

    python
    #!/usr/bin/env python
    import rospy
    from std_msgs.msg import String
    
    if __name__ == "__main__":
        rospy.init_node("talker_p")
        pub = rospy.Publisher("chatter", String, queue_size=10)
        msg = String()
        msg_front = "hello 你好"
        count = 0
        rate = rospy.Rate(10)  # 10Hz
    
        while not rospy.is_shutdown():
            msg.data = msg_front + str(count)
            pub.publish(msg)
            rospy.loginfo("Sent message: %s", msg.data)
            rate.sleep()
            count += 1
  3. Implementación del suscriptor:

    listener.py

    python
    #!/usr/bin/env python
    import rospy
    from std_msgs.msg import String
    
    def doMsg(msg):
        rospy.loginfo("Heard: %s", msg.data)
    
    if __name__ == "__main__":
        rospy.init_node("listener_p")
        sub = rospy.Subscriber("chatter", String, doMsg, queue_size=10)
        rospy.spin()
  4. Añadir permisos de ejecución:

    bash
     sudo chmod +x *.py
  5. Configuración de CMakeLists.txt:

    Añada el siguiente código al final del CMakeLists.txt de su paquete:

    cmake
    catkin_install_python(PROGRAMS
      scripts/talker.py
      scripts/listener.py
      DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
    )
  6. Ejecución del código:

    • Abra una terminal e inicie roscore:
      bash
      roscore
    • En una nueva terminal, navegue a su espacio de trabajo y ejecute el nodo publicador:
      bash
      rosrun listener_and_talker talker.py
    • En otra terminal, ejecute el nodo suscriptor:
      bash
      rosrun listener_and_talker listener.py

Debería ver mensajes que se publican y se reciben, mostrados en la terminal.

Comandos comunes para temas en ROS

  • rostopic bw: Mostrar el uso de ancho de banda de un tema
  • rostopic delay: Mostrar el retardo de un tema con cabecera
  • rostopic echo: Imprimir mensajes por pantalla
  • rostopic find: Buscar temas por tipo
  • rostopic hz: Mostrar la frecuencia de publicación de un tema
  • rostopic info: Mostrar información sobre un tema
  • rostopic list: Listar todos los temas activos
  • rostopic pub: Publicar datos en un tema
  • rostopic type: Imprimir el tipo de un tema

Introducción a la comunicación por servicios

La comunicación por servicios en ROS se diferencia de la comunicación por temas por ser bidireccional. Permite no solo el envío de mensajes, sino también la recepción de respuestas. Este modelo consta de dos partes principales:

  1. Cliente: La entidad que envía una petición.
  2. Servidor: La entidad que procesa la petición y envía una respuesta.

Cuando un cliente envía una petición a un servidor, espera a que el servidor procese la petición y devuelva una respuesta. Este mecanismo sigue una estructura "petición-respuesta", completando la comunicación.

¿Cómo funciona?

  • Nodo B (el servidor) proporciona una interfaz de servicio, normalmente con un nombre del estilo /service_name.
  • Nodo A (el cliente) envía una petición al Nodo B.
  • El Nodo B procesa la petición y devuelve una respuesta.

El proceso de comunicación se puede ilustrar de la siguiente manera:

  1. El nodo Talker anuncia un servicio a través del ROS Master:

    • El nodo Talker anuncia un servicio (p. ej., advertiseService("bar", foo:1234)) a través del ROS Master, indicando su disponibilidad.
  2. El nodo Listener busca el servicio a través del ROS Master:

    • El nodo Listener envía una petición al ROS Master para encontrar el servicio (p. ej., lookupService("bar")).
  3. El ROS Master devuelve la dirección del servicio:

    • El ROS Master responde con la dirección del servicio (p. ej., foo:3456) para que el nodo Listener se conecte.
  4. El nodo Listener solicita datos al nodo Talker:

    • El nodo Listener envía una petición de servicio al nodo Talker, usando XML/RPC para la comunicación.
  5. El nodo Talker responde con los datos solicitados:

    • El nodo Talker procesa la petición y envía los datos de respuesta a través de TCP.

    J3010

Puntos clave:

  • El cliente queda bloqueado hasta que recibe una respuesta del servidor.
  • La comunicación por servicios es eficiente, ya que solo consume recursos cuando es necesario (es decir, cuando se realiza una petición).

Modelo teórico

El modelo de comunicación por servicios involucra tres componentes clave:

  1. ROS Master: Gestiona el registro de servidores y clientes, ayudando a establecer conexiones basándose en la coincidencia de nombres de servicio.
  2. Servidor: Proporciona el servicio.
  3. Cliente: Solicita el servicio.

Resumen del proceso:

  1. Registro del servidor:

    • El servidor se registra ante el ROS Master, incluyendo el nombre del servicio que proporciona.
  2. Registro del cliente:

    • El cliente se registra ante el ROS Master, especificando el servicio que desea utilizar.
  3. Coincidencia y conexión:

    • El ROS Master empareja al cliente y al servidor según el nombre del servicio y facilita la conexión.
  4. Ciclo petición-respuesta:

    • El cliente envía una petición al servidor, que la procesa y devuelve una respuesta.

Comparación entre comunicación por temas y por servicios

Comparemos estos dos métodos de comunicación de ROS más comunes para profundizar nuestra comprensión:

AspectoComunicación por temasComunicación por servicios
Tipo de comunicaciónAsíncronaSíncrona
ProtocoloTCP/IPTCP/IP
Modelo de comunicaciónPublicar-SuscribirPetición-Respuesta
RelaciónMuchos a muchosUno a muchos
CaracterísticasBasada en callbacksLlamada a procedimiento remoto (RPC)
Casos de usoDatos continuos y de alta frecuenciaTareas específicas de baja frecuencia
EjemploPublicar datos de LiDARActivar un sensor o tomar una foto

Nota: La llamada a procedimiento remoto (RPC) consiste en ejecutar una función en un proceso distinto como si fuera local.

5. Crear un servicio personalizado (srv) en ROS

Veamos un ejemplo práctico en el que creamos un servicio personalizado que suma dos enteros enviados por el cliente. El servidor procesará esta petición y devolverá la suma al cliente.

Pasos para implementarlo:

  1. Crear un nuevo paquete

    bash
    cd ~/seeed_ws/src
    catkin_create_pkg service_communication roscpp rospy std_msgs
    cd ~/seeed_ws
    catkin_make
  2. Definir el archivo srv: El archivo srv define la estructura de la petición y la respuesta. En este caso, la petición contendrá dos enteros y la respuesta contendrá su suma. Cree un nuevo directorio llamado srv en su paquete y añada un archivo llamado AddInts.srv:

    bash
     mkdir ~/seeed_ws/src/service_communication/srv
     cd ~/seeed_ws/src/service_communication/srv
     touch AddInts.srv

    Copie lo siguiente en AddInts.srv:

    srv
    int32 num1
    int32 num2
    ---
    int32 sum

    J3010

  3. Actualizar package.xml: Añada las dependencias necesarias para generar archivos de mensaje en el package.xml del paquete:

    xml
    <build_depend>message_generation</build_depend>
    <exec_depend>message_runtime</exec_depend>

    J3010

  4. Actualizar CMakeLists.txt:

    • Incluya las configuraciones necesarias para generar los archivos de servicio en el CMakeLists.txt del paquete:
      cmake
      find_package(catkin REQUIRED COMPONENTS
        roscpp
        rospy
        std_msgs
        message_generation
      )
      
      add_service_files(
        FILES
        AddInts.srv
      )
      
      generate_messages(
        DEPENDENCIES
        std_msgs
      )

      J3010

  5. Compilar el paquete:

    • Compile el paquete para generar los encabezados del mensaje de servicio:
      bash
      cd ~/seeed_ws
      catkin_make
      source devel/setup.bash

Implementación de la comunicación por servicios (C++)

Este ejemplo demuestra cómo implementar la comunicación por servicios en ROS usando C++. Crearemos un servicio sencillo en el que el servidor suma dos enteros proporcionados por el cliente y devuelve la suma.

1. Implementación del servidor:

add_two_ints_server.cpp

cpp
#include "ros/ros.h"
#include "service_communication/AddInts.h"

// Callback function to handle the client's request
bool add(service_communication::AddInts::Request &req,
         service_communication::AddInts::Response &res) {
    res.sum = req.num1 + req.num2;  // Compute the sum
    ROS_INFO("Request: a=%ld, b=%ld", (long int)req.num1, (long int)req.num2);
    ROS_INFO("Sending back response: [%ld]", (long int)res.sum);
    return true;
}

int main(int argc, char **argv) {
    ros::init(argc, argv, "add_two_ints_server");
    ros::NodeHandle nh;

    // Advertise the service to the ROS master
    ros::ServiceServer service = nh.advertiseService("add_two_ints", add);
    ROS_INFO("Ready to add two integers.");
    ros::spin();

    return 0;
}

2. Implementación del cliente:

add_two_ints_client.cpp

cpp
#include "ros/ros.h"
#include "service_communication/AddInts.h"
#include <cstdlib>

int main(int argc, char **argv) {
    ros::init(argc, argv, "add_two_ints_client");
    if (argc != 3) {
        ROS_INFO("Usage: add_two_ints_client X Y");
        return 1;
    }

    ros::NodeHandle nh;
    ros::ServiceClient client = nh.serviceClient<service_communication::AddInts>("add_two_ints");

    // Prepare the service request
    service_communication::AddInts srv;
    srv.request.num1 = atoll(argv[1]);
    srv.request.num2 = atoll(argv[2]);

    // Call the service and check if it was successful
    if (client.call(srv)) {
        ROS_INFO("Sum: %ld", (long int)srv.response.sum);
    } else {
        ROS_ERROR("Failed to call service add_two_ints");
        return 1;
    }

    return 0;
}

Configuración de CMakeLists.txt:

Asegúrese de añadir las siguientes líneas al final de CMakeLists.txt para compilar tanto el servidor como el cliente:

cmake
add_executable(add_two_ints_server src/add_two_ints_server.cpp)
add_executable(add_two_ints_client src/add_two_ints_client.cpp)

add_dependencies(add_two_ints_server ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(add_two_ints_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})

Compilar y ejecutar la demo

Abra una terminal:

bash
cd ~/seeed_ws
catkin_make
roscore

Abra otra terminal:

bash
cd ~/seeed_ws
source devel/setup.bash
 rosrun service_communication server

Abra otra terminal:

bash
cd ~/seeed_ws
source devel/setup.bash
rosrun service_communication client 1 5

J3010

Implementación de la comunicación por servicios (Python)

Este ejemplo en Python logra la misma funcionalidad que el ejemplo en C++, donde se utiliza un servicio para sumar dos enteros.

Cree una carpeta scripts dentro del paquete y cree los archivos add_two_ints_server.py y add_two_ints_client.py dentro de ella.

bash
cd ~/seeed/src/service_communication/
mkdir scripts
cd scripts
touch add_two_ints_server.py add_two_ints_client.py

1. Implementación del servidor:

add_two_ints_server.py

python
#!/usr/bin/env python
import rospy
from service_communication.srv import AddInts,AddIntsRequest, AddIntsResponse
def doReq(req):
    sum = req.num1 + req.num2
    rospy.loginfo("data:num1 = %d, num2 = %d, sum = %d",req.num1, req.num2, sum)
    resp = AddIntsResponse(sum)
    return resp
if __name__ == "__main__":
    rospy.init_node("addints_server_p")
    server = rospy.Service("AddInts",AddInts,doReq)
    rospy.spin()

2. Implementación del cliente:

add_two_ints_client.py

python
#!/usr/bin/env python

import sys
import rospy
from service_communication.srv import *

if __name__ == "__main__":
    if len(sys.argv) != 3:
        rospy.logerr("error")
        sys.exit(1)
    rospy.init_node("AddInts_Client_p")
    client = rospy.ServiceProxy("AddInts",AddInts)
    client.wait_for_service()
    req = AddIntsRequest()
    req.num1 = int(sys.argv[1])
    req.num2 = int(sys.argv[2]) 
    resp = client.call(req)
    rospy.loginfo("result:%d",resp.sum)

Configuración de CMakeLists.txt:

Añada las siguientes líneas en su CMakeLists.txt para los scripts de Python:

cmake
catkin_install_python(PROGRAMS
  scripts/add_two_ints_server.py 
  scripts/add_two_ints_client.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

Compilar y ejecutar la demo

Abra una terminal:

bash
cd ~/seeed_ws
catkin_make
roscore

Abra otra terminal:

bash
cd ~/seeed_ws
source devel/setup.bash
rosrun service_communication add_two_ints_server.py

Abra otra terminal:

bash
cd ~/seeed_ws
source devel/setup.bash
rosrun service_communication add_two_ints_client.py 1 5

Comandos de comunicación por servicios

Para trabajar con servicios en ROS, utilizará el comando rosservice. Aquí tiene una lista de los comandos rosservice más comunes y sus funciones:

  • rosservice args: Imprimir los argumentos requeridos por un servicio
  • rosservice call: Llamar a un servicio con los argumentos proporcionados
  • rosservice find: Buscar servicios por tipo
  • rosservice info: Imprimir información sobre un servicio
  • rosservice list: Listar todos los servicios activos
  • rosservice type: Imprimir el tipo de un servicio
  • rosservice uri: Imprimir el URI de ROSRPC de un servicio

Introducción al servidor de parámetros de ROS

El servidor de parámetros de ROS es un espacio de almacenamiento compartido, multiusuario y accesible por red para parámetros. Proporciona una manera de almacenar y recuperar parámetros en tiempo de ejecución, que pueden usarse para configurar nodos o compartir datos entre ellos. Los parámetros del servidor pueden ser de varios tipos de datos, incluidos enteros, booleanos, cadenas, doubles, listas y diccionarios. El servidor de parámetros lo gestiona el ROS Master, y los nodos interactúan con él estableciendo, recuperando o eliminando parámetros.

Modelo teórico del servidor de parámetros

El servidor de parámetros implica tres roles principales:

  1. ROS Master: Gestiona el servidor de parámetros, actuando como almacenamiento central de los parámetros.
  2. Talker: Un nodo que establece parámetros en el servidor.
  3. Listener: Un nodo que recupera parámetros del servidor.

El proceso de interacción con el servidor de parámetros normalmente implica los siguientes pasos:

  1. Establecer parámetros (Talker):

    • El nodo Talker envía un parámetro al servidor de parámetros mediante RPC (llamada a procedimiento remoto), incluyendo el nombre y valor del parámetro. El ROS Master almacena este parámetro en su lista.
  2. Recuperar parámetros (Listener):

    • El nodo Listener solicita un parámetro al servidor de parámetros enviando una consulta con el nombre del parámetro.
  3. Devolver parámetros (ROS Master):

    • El ROS Master busca el parámetro solicitado en su almacenamiento y devuelve el valor correspondiente al Listener.

    J3010

Tipos de datos admitidos:

  • Enteros de 32 bits
  • Booleanos
  • Cadenas
  • Doubles
  • Fechas ISO8601
  • Listas
  • Datos binarios codificados en Base64
  • Diccionarios

Implementación en C++

Establecer parámetros (C++):

Comencemos estableciendo varios tipos de parámetros en el servidor de parámetros utilizando dos APIs distintas: ros::NodeHandle y ros::param.

set_parameters.cpp

cpp
#include "ros/ros.h"

int main(int argc, char *argv[]) {
    ros::init(argc, argv, "set_parameters");

    std::vector<std::string> students = {"Alice", "Bob", "Charlie", "David"};
    std::map<std::string, std::string> friends = {{"John", "Doe"}, {"Jane", "Smith"}};

    // Using ros::NodeHandle to set parameters
    ros::NodeHandle nh;
    nh.setParam("int_param", 42);
    nh.setParam("double_param", 3.14159);
    nh.setParam("bool_param", true);
    nh.setParam("string_param", "Hello ROS");
    nh.setParam("vector_param", students);
    nh.setParam("map_param", friends);

    // Using ros::param to set parameters
    ros::param::set("int_param_param", 84);
    ros::param::set("double_param_param", 6.28318);
    ros::param::set("bool_param_param", false);
    ros::param::set("string_param_param", "Goodbye ROS");
    ros::param::set("vector_param_param", students);
    ros::param::set("map_param_param", friends);

    return 0;
}

Añada el siguiente código al final del CMakeLists.txt de su paquete:

cmake
add_executable(set_parameters src/set_parameters.cpp)
target_link_libraries(set_parameters ${catkin_LIBRARIES})

En este ejemplo:

  • Establecemos varios tipos de parámetros en el servidor de parámetros, incluidos enteros, doubles, booleanos, cadenas, vectores y mapas.
  • Usamos las APIs ros::NodeHandle y ros::param para establecer los parámetros.

Recuperar parámetros (C++):

A continuación, recuperaremos los parámetros que previamente establecimos en el servidor de parámetros.

get_parameters.cpp

cpp
#include "ros/ros.h"

int main(int argc, char *argv[]) {
    ros::init(argc, argv, "get_parameters");

    // Using ros::NodeHandle to retrieve parameters
    ros::NodeHandle nh;
    int int_value;
    double double_value;
    bool bool_value;
    std::string string_value;
    std::vector<std::string> students;
    std::map<std::string, std::string> friends;

    nh.getParam("int_param", int_value);
    nh.getParam("double_param", double_value);
    nh.getParam("bool_param", bool_value);
    nh.getParam("string_param", string_value);
    nh.getParam("vector_param", students);
    nh.getParam("map_param", friends);

    ROS_INFO("Retrieved values:");
    ROS_INFO("int_param: %d", int_value);
    ROS_INFO("double_param: %.5f", double_value);
    ROS_INFO("bool_param: %d", bool_value);
    ROS_INFO("string_param: %s", string_value.c_str());

    for (const auto &student : students) {
        ROS_INFO("Student: %s", student.c_str());
    }

    for (const auto &friend_pair : friends) {
        ROS_INFO("Friend: %s = %s", friend_pair.first.c_str(), friend_pair.second.c_str());
    }

    return 0;
}

Añada el siguiente código al final del CMakeLists.txt de su paquete:

cmake
add_executable(get_parameters src/get_parameters.cpp)
target_link_libraries(get_parameters ${catkin_LIBRARIES})

En este ejemplo:

  • Recuperamos los parámetros establecidos en el servidor mediante la API ros::NodeHandle.
  • Los parámetros recuperados se imprimen en el log de ROS para su verificación.

Eliminar parámetros (C++):

Por último, veamos cómo eliminar parámetros del servidor de parámetros.

delete_parameters.cpp

cpp
#include "ros/ros.h"

int main(int argc, char *argv[]) {
    ros::init(argc, argv, "delete_parameters");

    ros::NodeHandle nh;
    bool success;

    // Using ros::NodeHandle to delete parameters
    success = nh.deleteParam("int_param");
    ROS_INFO("Delete int_param: %s", success ? "Success" : "Failure");

    // Using ros::param to delete parameters
    success = ros::param::del("int_param_param");
    ROS_INFO("Delete int_param_param: %s", success ? "Success" : "Failure");

    return 0;
}

Añada el siguiente código al final del CMakeLists.txt de su paquete:

cmake
add_executable(delete_parameters src/delete_parameters.cpp)
target_link_libraries(delete_parameters ${catkin_LIBRARIES})

En este ejemplo:

  • Usamos las APIs ros::NodeHandle y ros::param para eliminar parámetros del servidor.
  • El éxito de la eliminación queda registrado en el log.

2.2 Implementación en Python

Establecer parámetros (Python):

Ahora vamos a establecer parámetros usando Python. El proceso es muy similar a la versión en C++.

python
#!/usr/bin/env python

import rospy

if __name__ == "__main__":
    rospy.init_node("set_parameters_py")

    # Setting various types of parameters
    rospy.set_param("int_param", 42)
    rospy.set_param("double_param", 3.14159)
    rospy.set_param("bool_param", True)
    rospy.set_param("string_param", "Hello ROS")
    rospy.set_param("list_param", ["apple", "banana", "cherry"])
    rospy.set_param("dict_param", {"first_name": "John", "last_name": "Doe"})

    # Modifying a parameter
    rospy.set_param("int_param", 84)

Añada el siguiente código al final del CMakeLists.txt de su paquete:

cmake
catkin_install_python(PROGRAMS
  scripts/set_parameters_py.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

En este ejemplo:

  • Establecemos varios tipos de parámetros, incluidos enteros, doubles, booleanos, cadenas, listas y diccionarios.
  • También demostramos cómo modificar un parámetro existente.

Recuperar parámetros (Python):

A continuación, recuperaremos los parámetros que establecimos.

python
#!/usr/bin/env python

import rospy

if __name__ == "__main__":
    rospy.init_node("get_parameters_py")

    # Retrieving parameters
    int_value = rospy.get_param("int_param", 0)
    double_value = rospy.get_param("double_param", 0.0)
    bool_value = rospy.get_param("bool_param", False)
    string_value = rospy.get_param("string_param", "")
    list_value = rospy.get_param("list_param", [])
    dict_value = rospy.get_param("dict_param", {})

    rospy.loginfo("Retrieved values:")
    rospy.loginfo("int_param: %d", int_value)
    rospy.loginfo("double_param: %.5f", double_value)
    rospy.loginfo("bool_param: %s", bool_value)
    rospy.loginfo("string_param: %s", string_value)
    rospy.loginfo("list_param: %s", list_value)
    rospy.loginfo("dict_param: %s", dict_value)

Añada el siguiente código al final del CMakeLists.txt de su paquete:

cmake
catkin_install_python(PROGRAMS
  scripts/set_parameters_py.py
  scripts/get_parameters_py.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

En este ejemplo:

  • Usamos rospy.get_param para recuperar parámetros establecidos en el servidor.
  • Los valores recuperados se registran usando rospy.loginfo.

Eliminar parámetros (Python):

Por último, eliminemos parámetros del servidor de parámetros usando Python.

python
#!/usr/bin/env python

import rospy

if __name__ == "__main__":
    rospy.init_node("delete_parameters_py")

    try:
        rospy.delete_param("int_param")
        rospy.loginfo("int_param deleted successfully.")
    except KeyError:
        rospy.logwarn("int_param does not exist.")

    try:
        rospy.delete_param("non_existent_param")
        rospy.loginfo("non_existent_param deleted successfully.")
    except KeyError:
        rospy.logwarn("non_existent_param does not exist.")

Añada el siguiente código al final del CMakeLists.txt de su paquete:

cmake
catkin_install_python(PROGRAMS
  scripts/set_parameters_py.py
  scripts/get_parameters_py.py
  scripts/delete_parameters_py.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

En este ejemplo:

  • Intentamos eliminar un parámetro y manejamos el caso en que no existe usando manejo de excepciones (KeyError).

Comandos comunes del servidor de parámetros de ROS

rosparam incluye herramientas de línea de comandos para obtener y establecer parámetros de ROS en el servidor de parámetros, utilizando archivos codificados en YAML.

  • rosparam set: Establecer un parámetro
  • rosparam get: Obtener un parámetro
  • rosparam load: Cargar parámetros desde un archivo externo
  • rosparam dump: Volcar parámetros a un archivo externo
  • rosparam delete: Eliminar un parámetro
  • rosparam list: Listar todos los parámetros

Ejemplos:

  • rosparam list: Listar todos los parámetros del servidor de parámetros.
  • rosparam set <param_name> <value>: Establecer un parámetro con un valor específico.
  • rosparam get <param_name>: Obtener el valor de un parámetro específico.
  • rosparam delete <param_name>: Eliminar un parámetro específico.
  • rosparam load <file_name.yaml>: Cargar parámetros desde un archivo YAML.
  • rosparam dump <file_name.yaml>: Volcar los parámetros actuales a un archivo YAML.