Definición y uso de datos del servicio de entrada de desarrollo de aplicaciones ROS

ROS es la abreviatura de Robot Operating System Este artículo presenta la introducción del desarrollo de aplicaciones ROS, la definición y el uso de datos de servicio. La comunicación entre el cliente y el servidor utiliza datos de servicio. Este artículo primero define los datos de un servicio. Después de que la compilación sea exitosa, use un servidor y un cliente para verificar. El cliente también puede usar la llamada rosservice directamente, de modo que el cliente no necesite un programa. La verificación de la prueba es primero el código C ++ y luego el código Python. También puede optar por ver solo el que conoce.

Creación de paquetes de funciones

Este artículo es   una continuación de la programación del Cliente Cliente en la introducción al desarrollo de aplicaciones ROS . Si ha creado un paquete de funciones en ese artículo, no lo necesita aquí, simplemente omita esta sección.

El  espacio de trabajo de ROS  se establece en el artículo Desarrollo de ROS y preparación de aplicaciones: crear un espacio de trabajo . Ahora, cree un paquete funcional:

cd ~ / catkin_ws / src

catkin_create_pkg servicio_de_aprendizaje std_msgs roscpp rospy geometry_msgs turtlesim
 

Datos de servicio personalizados

Cree un nuevo directorio srv en el directorio del paquete del proyecto

cd ~ / catkin_ws / src / learning_service

mkdir srv

cd srv

Luego crea un nuevo archivo Person.srv

nano Person.srv

El contenido del archivo es:

string name
uint8  age
uint8  sex

uint8 unknown = 0
uint8 male    = 1
uint8 female  = 2

---
string result

Echemos un vistazo a las características de este archivo:

 

Los datos de la solicitud y los datos de la respuesta están separados por --- 3 líneas horizontales-, la parte superior son los datos de la solicitud y la parte inferior son los datos de la respuesta.

Lo anterior es para enviar datos, el tipo de datos que no está asignado es el tipo de datos y el valor asignado puede ser una clase de enumeración, por lo que debe ingresar 3 variables nombre de cadena, uint8 age, uint8 sex

A continuación se muestran los datos de respuesta, aquí hay solo una cadena

 

Regrese al directorio del paquete del proyecto, abra y edite package.xml:

 cd ~ / catkin_ws / src / learning_service

nano package.xml

Agregue las siguientes 2 líneas:

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


La posición agregada se refiere a la siguiente posición, que está encima del comentario delante de <export>:

 <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <exec_depend>turtlesim</exec_depend>
 
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>
 
  <!-- The export tag contains other, unspecified, tags -->
  <export>


Luego abra y edite CMakeLists.txt, un total de 3

nano CMakeLists.txt

Primero agregue message_generation en find_package y
agréguelo de la siguiente manera:

find_package(catkin REQUIRED COMPONENTS
  geometry_msgs
  roscpp
  rospy
  std_msgs
  turtlesim
  message_generation
)

 Agregue el siguiente código, que también se puede usar como 2 líneas,

add_service_files(
  FILES
  Person.srv
)

generate_messages(
  DEPENDENCIES
  std_msgs
)

La ubicación para agregar es la siguiente: 

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   geometry_msgs#   std_msgs
# )

add_service_files(
  FILES
  Person.srv
)

generate_messages(
  DEPENDENCIES
  std_msgs
)

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

En catkin_package, descomente la línea CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim y agregue message_runtime para
tener el siguiente efecto:

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES learning_topic
   CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim message_runtime
#  DEPENDS system_lib
)

Después de modificar estos dos archivos, compile en el espacio de trabajo.

La compilación debe volver al directorio ~ / catkin_ws

cd ~ / catkin_ws

catkin_make

Si la compilación se realiza correctamente, los datos del servicio están definidos y listos.

Mira la etapa final de la información de compilación.

Scanning dependencies of target learning_service_generate_messages_py
[ 40%] Generating Python code from SRV learning_service/Person
[ 45%] Generating Python srv __init__.py for learning_service
[ 45%] Built target turtle_command_server
Scanning dependencies of target learning_service_generate_messages_eus
[ 50%] Generating EusLisp code from learning_service/Person.srv
[ 54%] Generating EusLisp manifest code for learning_service
[ 54%] Built target learning_service_generate_messages_py
Scanning dependencies of target learning_service_generate_messages_nodejs
[ 59%] Generating Javascript code from learning_service/Person.srv
[ 59%] Built target learning_service_generate_messages_nodejs
Scanning dependencies of target learning_service_generate_messages_cpp
[ 63%] Generating C++ code from learning_service/Person.srv
[ 63%] Built target learning_service_generate_messages_cpp
Scanning dependencies of target learning_service_generate_messages_lisp
[ 68%] Generating Lisp code from learning_service/Person.srv
[ 68%] Built target learning_service_generate_messages_lisp
[ 72%] Built target learning_topic_generate_messages_nodejs
[ 77%] Built target learning_topic_generate_messages_cpp
[ 86%] Built target learning_topic_generate_messages_eus
[ 95%] Built target learning_topic_generate_messages_py
[100%] Built target learning_topic_generate_messages_lisp
[100%] Built target learning_topic_generate_messages
[100%] Built target learning_service_generate_messages_eus
Scanning dependencies of target learning_service_generate_messages
[100%] Built target learning_service_generate_messages

Parece estar listo para varios idiomas.

c ++ verificar el código fuente

Para usar los datos del servicio para verificar, necesita dos programas para el servidor y el cliente, y los colocamos en el directorio src del directorio del proyecto.

Vaya al directorio src y cree los archivos person_client.cpp y person_server.cpp.cpp respectivamente

cd ~ / catkin_ws / src / servicio_aprendizaje / src

nano person_client.cpp

El contenido del archivo es:

/**
 * 该例程将请求/show_person服务,服务数据类型learning_service::Person
 */

#include <ros/ros.h>
#include "learning_service/Person.h"

int main(int argc, char** argv)
{
    // 初始化ROS节点
        ros::init(argc, argv, "person_client");

    // 创建节点句柄
        ros::NodeHandle node;

    // 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
        ros::service::waitForService("/show_person");
        ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person");

    // 初始化learning_service::Person的请求数据
        learning_service::Person srv;
        srv.request.name = "Tom";
        srv.request.age  = 20;
        srv.request.sex  = learning_service::Person::Request::male;

    // 请求服务调用
        ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]", 
                         srv.request.name.c_str(), srv.request.age, srv.request.sex);

        person_client.call(srv);

        // 显示服务调用结果
        ROS_INFO("Show person result : %s", srv.response.result.c_str());

        return 0;
};

nano person_server.cpp

El contenido del archivo es:

/**
 * 该例程将执行/show_person服务,服务数据类型learning_service::Person
 */
 
#include <ros/ros.h>
#include "learning_service/Person.h"

// service回调函数,输入参数req,输出参数res
bool personCallback(learning_service::Person::Request  &req,
                                learning_service::Person::Response &res)
{
    // 显示请求数据
    ROS_INFO("Person: name:%s  age:%d  sex:%d", req.name.c_str(), req.age, req.sex);

        // 设置反馈数据
        res.result = "OK";

    return true;
}

int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "person_server");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个名为/show_person的server,注册回调函数personCallback
    ros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);

    // 循环等待回调函数
    ROS_INFO("Ready to show person informtion.");
    ros::spin();

    return 0;
}


2 archivos están listos.

Configurar el archivo cmake

En el directorio ~ / catkin_ws / src / learning_service /, hay un archivo CMakeLists.txt, necesitamos modificar este archivo

cd ~ / catkin_ws / src / learning_service /

nano CMakeLists.txt 

Agregue las siguientes líneas a este archivo,

add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)

add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)

La posición agregada es el final de la sección Build. Consulte la siguiente posición, que está frente a ## install ##, y luego el cliente anterior y el servidor agregan 2 líneas después de cada una:

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )
add_executable(turtle_spawn src/turtle_spawn.cpp)
target_link_libraries(turtle_spawn ${catkin_LIBRARIES})

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

add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)

add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)

#############
## Install ##
#############

Guardar la salida

Esto completa la compilación y configuración.

Compila y ejecuta la prueba

La compilación debe volver al directorio ~ / catkin_ws

cd ~ / catkin_ws

catkin_make

Debe obtenerse una vez después de la compilación:

fuente devel / setup.bash

Si hay un error en la compilación, el error debe eliminarse y la prueba se ejecutará después de que se complete la compilación.

Abra una terminal, inicie ros, ejecute

roscore

Abra otra terminal, inicie el servidor y ejecute

rosrun learning_service person_server

Abra otra terminal e inicie el cliente:

rosrun learning_service person_client

De hecho, también puede utilizar rosservice directamente como cliente para realizar pruebas.

rosservice call / show_person leon 12 2

o

leon @ ubuntu: ~ $ rosservice call / show_person "nombre: 'Leon'
edad: 50
sexo: 20" Los 
resultados de ejecución del programa son los siguientes: el cliente primero ejecuta el cliente dos veces, luego la llamada rosservice dos veces y luego el cliente nuevamente

La verificación de c ++ es exitosa.

Python verificar el código fuente

Para verificar los datos del servicio se requieren dos programas, el lado del servidor y el lado del cliente, los colocamos en el directorio de scripts del directorio del proyecto.

Vaya al directorio de scripts y cree los archivos person_client.py y person_server.py respectivamente, si no, cree uno (scripts mkdir).

~ / catkin_ws / src / learning_service / scripts

nano person_server.py

El contenido del archivo es:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 该例程将执行/show_person服务,服务数据类型learning_service::Person

import rospy
from learning_service.srv import Person, PersonResponse

def personCallback(req):
	# 显示请求数据
    rospy.loginfo("Person: name:%s  age:%d  sex:%d", req.name, req.age, req.sex)

	# 反馈数据
    return PersonResponse("OK")

def person_server():
	# ROS节点初始化
    rospy.init_node('person_server')

	# 创建一个名为/show_person的server,注册回调函数personCallback
    s = rospy.Service('/show_person', Person, personCallback)

	# 循环等待回调函数
    print "Ready to show person informtion."
    rospy.spin()

if __name__ == "__main__":
    person_server()


nano person_client.py

El contenido del archivo es:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 该例程将请求/show_person服务,服务数据类型learning_service::Person

import sys
import rospy
from learning_service.srv import Person, PersonRequest

def person_client():
	# ROS节点初始化
    rospy.init_node('person_client')

	# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
    rospy.wait_for_service('/show_person')
    try:
        person_client = rospy.ServiceProxy('/show_person', Person)

		# 请求服务调用,输入请求数据
        response = person_client("Tom", 20, PersonRequest.male)
        return response.result
    except rospy.ServiceException, e:
        print "Service call failed: %s"%e

if __name__ == "__main__":
	#服务调用并显示调用结果
    print "Show person result : %s" %(person_client())


Ejecutar prueba

Porque no es necesario compilar python, pero debe configurarse como un archivo ejecutable

chmod + x * .py

Abra una terminal, inicie ros, ejecute

roscore

Primera fuente:

fuente ~ / catkin_ws / devel / setup.bash

Abra otra terminal, inicie el servidor y ejecute

rosrun learning_service person_server.py 

Abra otra terminal e inicie el cliente:

rosrun learning_service person_client.py

La autenticación del cliente también puede usar directamente la llamada rosservice

rosservice call / show_person leon 12 2

o

leon @ ubuntu: ~ $ rosservice call / show_person "nombre: 'Leon'
edad: 50
sexo: 20" 

rosservice list puede enumerar todos los nombres de servicios.

Los resultados del programa son los siguientes:

 

La verificación de Python es exitosa.

El código fuente también se puede descargar en https://github.com/huchunxu/ros_21_tutorials

El texto completo se presenta aquí.
 

Supongo que te gusta

Origin blog.csdn.net/leon_zeng0/article/details/114994859
Recomendado
Clasificación