[Tutorial de ROS] Tema Comunicación


1. Proceso

La comunicación de temas es el modo de comunicación más utilizado en ROS y se basa en el modo de publicación-suscripción, es decir, un nodo publica un mensaje y otro nodo se suscribe al mensaje. En ROS, implementar la comunicación por temas solo requiere los siguientes pasos:

  1. Para determinar el tipo de datos que se publicarán, generalmente necesita personalizar el archivo .msg, modificar el archivo CMakeLists.txt y el archivo package.xml y volver a compilar.
  2. Escriba los archivos cpp del editor y del suscriptor, modifique el archivo CMakeLists.txt y vuelva a compilar
  3. Inicie el nodo de editor y el nodo de suscriptor por separado, el orden no importa

2. Personaliza los datos de publicación

En el protocolo de comunicación ROS, el soporte de datos es un componente importante. Algunos tipos de datos nativos se encapsulan en ROS a través de std_msgs. Sin embargo, estos datos generalmente solo contienen un campo de datos. La estructura única significa limitaciones funcionales. Al transmitir algunos datos complejos, std_msgs es inadecuado debido a una mala descripción. En este escenario, debe escribir un archivo .msg desde Definir el tipo de mensaje.

2.1 tipo incorporado std_msgs

  • Correspondencia entre tipos integrados y C++ y Python:
Tipo primitivo C++ Pitón
booleano uint8_t booleano
tu8 int8_t En t
uint8 uint8_t En t
int16 int16_t En t
uint16 uint16_t En t
int32 uint32_t En t
uint64 uint64_t largo int
flotador32 flotar flotar
flotador64 doble flotar
cadena std::cadena cadena de bytes
tiempo rosa::Tiempo Rospy.Tiempo
duración ros::Duración rospy.Duración
  • Correspondencia entre matrices de tipos integrados y C++ y Python:
Tipo primitivo C++ Pitón
Longitud variable estándar::vector tupla
longitud fija boost::array<T, longitud>或std::vector tupla

2.2 Escribir archivo .msg

Los ejemplos son los siguientes:

#文件名Person.msg
string name
uint16 age
float64 height

2.3 Modificar el archivo package.xml

  • Compruebe si existen las siguientes dependencias de compilación
<build_depend>message_generation</build_depend>
  • Compruebe si existen las siguientes dependencias de ejecución
<exec_depend>message_generation</exec_depend>

2.3.1 Archivo paquete.xml completo

<?xml version="1.0"?>
<package format="2">
  <name>chat</name>
  <version>0.0.0</version>
  <description>The chat package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
  <maintainer email="[email protected]">xu736946693</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/chat</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="[email protected]">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>message_generation</build_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>message_generation</exec_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

2.4 Modificar el archivo CMakeLists.txt

2.4.1 Modificar el comando find_package

# 需要加入 message_generation,必须有 std_msgs
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)

2.4.2 Agregar instrucción add_message_files

## 配置 msg 源文件
add_message_files(
  FILES
  Person.msg
)

2.4.3 Agregar directiva generate_messages

generate_messages(
  DEPENDENCIES
  std_msgs
)

2.4.4 Modificar la directiva catkin_package

#执行时依赖
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES demo02_talker_listener
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)

Entre ellos, la instrucción add_message_files debe estar delante de la instrucción generate_messages y luego se puede compilar en el directorio del espacio de trabajo.

2.5 Ver archivos de encabezado

Después de los pasos anteriores, ${workspace}/devel/include/${package}/debería aparecer un archivo de encabezado en el directorio, como se muestra en la figura:
Insertar descripción de la imagen aquí

  • Si no aparece, no se podrán realizar los siguientes pasos. En este momento, solo necesita ${workspace}/eliminar todos los directorios de compilación y desarrollo en el directorio y luego volver a compilar.
rm -rf build/
rm -rf devel/
catkin_make

3.Escribir archivo cpp

3.1 Árbol de archivos del directorio del paquete de funciones

Insertar descripción de la imagen aquí

3.2 Modificar el archivo CMakeLists.txt

3.2.1 Agregar directiva add_executable

add_executable(publisher
        src/publisher.cpp)
add_executable(listener
        src/listener.cpp)

3.2.2 Agregar directiva add_dependencies

add_dependencies(publisher ${
    
    PROJECT_NAME}_generate_messages_cpp)
add_dependencies(listener ${
    
    PROJECT_NAME}_generate_messages_cpp)

3.2.3 Agregar directiva target_link_libraries

target_link_libraries(person_talker
  ${
    
    catkin_LIBRARIES}
)
target_link_libraries(person_listener
  ${
    
    catkin_LIBRARIES}
)

3.2.4 Completar CMakeLists.txt

  • Muchas de estas declaraciones son generadas automáticamente por catkin_make
cmake_minimum_required(VERSION 3.0.2)
project(chat)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)


## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

# Generate messages in the 'msg' folder
 add_message_files(
   FILES
   Person.msg
 )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# 生成消息时依赖于 std_msgs
generate_messages(
        DEPENDENCIES
        std_msgs
)


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

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
#执行时依赖
catkin_package(
        #  INCLUDE_DIRS include
        #  LIBRARIES demo02_talker_listener
        CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
        #  DEPENDS system_lib
)


###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${
    
    catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${
      
      PROJECT_NAME}
#   src/${
      
      PROJECT_NAME}/pkg1.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${
      
      PROJECT_NAME} ${
      
      ${
      
      PROJECT_NAME}_EXPORTED_TARGETS} ${
      
      catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${
      
      PROJECT_NAME}_node src/pkg1_node.cpp)
add_executable(publisher
        src/publisher.cpp)
add_executable(listener
        src/listener.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${
      
      PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${
      
      PROJECT_NAME}_node ${
      
      ${
      
      PROJECT_NAME}_EXPORTED_TARGETS} ${
      
      catkin_EXPORTED_TARGETS})
add_dependencies(publisher ${
    
    PROJECT_NAME}_generate_messages_cpp)
add_dependencies(listener ${
    
    PROJECT_NAME}_generate_messages_cpp)

## Specify libraries to link a library or executable target against
# target_link_libraries(${
      
      PROJECT_NAME}_node
#   ${
    
    catkin_LIBRARIES}
# )

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

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${
      
      CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${
      
      PROJECT_NAME}_node
#   RUNTIME DESTINATION ${
      
      CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${
      
      PROJECT_NAME}
#   ARCHIVE DESTINATION ${
      
      CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${
      
      CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${
      
      CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${
      
      PROJECT_NAME}/
#   DESTINATION ${
      
      CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${
      
      CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${
      
      PROJECT_NAME}-test test/test_pkg1.cpp)
# if(TARGET ${
      
      PROJECT_NAME}-test)
#   target_link_libraries(${
      
      PROJECT_NAME}-test ${
      
      PROJECT_NAME})
# endif()
target_link_libraries(publisher
        ${
    
    catkin_LIBRARIES}
        )

target_link_libraries(listener
        ${
    
    catkin_LIBRARIES}
        )

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

3.3 CPP del editor

Los ejemplos son los siguientes:

/*
    需求: 实现基本的话题通信,一方发布数据,一方接收数据,
         实现的关键点:
         1.发送方
         2.接收方
         3.数据

         PS: 二者需要设置相同的话题


    消息发布方:
        循环发布信息:HelloWorld 后缀数字编号

    实现流程:
        1.包含头文件
        2.初始化 ROS 节点:命名(唯一)
        3.实例化 ROS 句柄
        4.实例化 发布者 对象
        5.组织被发布的数据,并编写逻辑发布数据

*/
// 1.包含头文件
#include "ros/ros.h"
#include "chat/Person.h"

int main(int argc, char  *argv[])
{
    
    
    //设置编码
    setlocale(LC_ALL,"");

    //2.初始化 ROS 节点:命名(唯一)
    // 参数1和参数2 后期为节点传值会使用
    // 参数3 是节点名称,是一个标识符,需要保证运行后,在 ROS 网络拓扑中唯一
    ros::init(argc,argv,"talker");
    //3.实例化 ROS 句柄
    ros::NodeHandle nh;//该类封装了 ROS 中的一些常用功能

    //4.实例化 发布者 对象
    //泛型: 发布的消息类型
    //参数1: 要发布到的话题
    //参数2: 队列中最大保存的消息数,超出此阀值时,先进的先销毁(时间早的先销毁)
    ros::Publisher pub = nh.advertise<chat::Person>("chatter",10);

    //5.组织被发布的数据,并编写逻辑发布数据
    //数据(动态组织)
    chat::Person p;
    p.name = "sunwukong";
    p.age = 2000;
    p.height = 1.45;

    //逻辑(一秒1次)
    ros::Rate r(1);

    //节点不死
    while (ros::ok())
    {
    
    
        //发布消息
        pub.publish(p);
        //加入调试,打印发送的消息
        ROS_INFO("我叫:%s,今年%d岁,高%.2f米", p.name.c_str(), p.age, p.height);p.age++;
        //根据前面制定的发送贫频率自动休眠 休眠时间 = 1/频率;
        r.sleep();
        //暂无应用
        ros::spinOnce();
    }


    return 0;
}

3.4 Cpp del suscriptor

Los ejemplos son los siguientes:

/*
    需求: 实现基本的话题通信,一方发布数据,一方接收数据,
         实现的关键点:
         1.发送方
         2.接收方
         3.数据


    消息订阅方:
        订阅话题并打印接收到的消息

    实现流程:
        1.包含头文件
        2.初始化 ROS 节点:命名(唯一)
        3.实例化 ROS 句柄
        4.实例化 订阅者 对象
        5.处理订阅的消息(回调函数)
        6.设置循环调用回调函数

*/
// 1.包含头文件
#include "ros/ros.h"
#include "chat/Person.h"

void doMsg(const chat::Person::ConstPtr& person_p){
    
    
    ROS_INFO("订阅的人信息:%s, %d, %.2f", person_p->name.c_str(), person_p->age, person_p->height);
}
int main(int argc, char  *argv[])
{
    
    
    //设置编码
    setlocale(LC_ALL,"");
    //2.初始化 ROS 节点:命名(唯一)
    ros::init(argc,argv,"listener");
    //3.实例化 ROS 句柄
    ros::NodeHandle nh;

    //4.实例化 订阅者 对象
    ros::Subscriber sub = nh.subscribe<chat::Person>("chatter",10,doMsg);
    //5.处理订阅的消息(回调函数)

    //     6.设置循环调用回调函数
    ros::spin();//循环读取接收的数据,并调用回调函数处理

    return 0;
}

4.Efecto

Insertar descripción de la imagen aquí

  • Si no se puede encontrar el archivo ejecutable, elimine la carpeta de compilación y la carpeta de desarrollo en el directorio de trabajo y vuelva a compilar.

Supongo que te gusta

Origin blog.csdn.net/qq_50791664/article/details/129964078
Recomendado
Clasificación