2 ROS1通讯编程基础(2)

2023-05-16

2 ROS1通讯编程基础

  • 2.3 配置文件的解读
    • 2.3.1 CMakeList.txt解读
      • 2.3.1.1 find_package的配置
      • 2.3.1.2 messages, services and actions的配置
      • 2.3.1.3 动态重配参数
      • 2.3.1.4 catkin_package的配置
      • 2.3.1.5 include_package配置
      • 2.3.1.6 C++编译配置
      • 2.3.1.7 Python配置
      • 2.3.1.8 参考文献
    • 2.3.2 package.xml文件解读
  • 2.4 服务通讯编程
    • 2.4.1 服务通讯理论模型
    • 2.4.2 服务通讯的基本编程
      • 2.4.2.1 编写srv服务文件
      • 2.4.2.2 配置自定义服务文件
      • 2.4.2.3 编译自定义服务文件并查看中间文件
      • 2.4.2.4 编译C++代码调用自定义服务
      • 2.4.2.5 编译Python代码调用自定义服务
    • 2.4.3 服务通讯编程总结
      • 2.4.3.1 服务通讯流程
      • 2.4.3.2 服务编程代码逻辑
      • 2.4.3.3 参考文献

  • 其他ROS1学习笔记: ROS1学习笔记
  • 代码仓库:Github连接地址
  • 欢迎各位互相学习交流

2.3 配置文件的解读

2.3.1 CMakeList.txt解读

CMakeList.txt作为ROS编程里,最需要配置的内容,对其默认文档进行解读,主要包括以下几个部分:其中重点在于find_package、一些自定义内容的配置、catkin_package和C++的配置,而且根据之前配置C++时候发现,配置的顺序对编译是有影响的,一般按照下图从左到右的顺序进行配置声明。

图片.png

2.3.1.1 find_package的配置

  1. 新建功能包就包括的依赖项;可以说是功能包编译时候需要的依赖项;
  2. 例如find_package(catkin REQUIRED COMPONENTS roscpp ...其他依赖项名)等

图片.png

2.3.1.2 messages, services and actions的配置

  1. 在msg文件夹下创建自定义消息,然后配置add_message_files(FILES 自定义消息.msg ...其他自定义消息.msg)
  2. 在srv文件夹下创建自定义服务,然后配置add_service_files(FILES 自定义.srv ...其他自定义服务)
  3. 在action文件夹下创建动作内容,然后配置add_action_files(FILES 自定义.action ...其他自定义服务)
  4. 构建自定义messages和services需要的依赖项,generate_messages(DEPENDENCIES std_msgs ...其他依赖项名字)

图片.png

2.3.1.3 动态重配参数

官方声明为Declare ROS dynamic reconfigure parameters:其中内容包括generate_dynamic_reconfigure_options(cfg/DynReconf1.cfg ...其他cfg)

图片.png

2.3.1.4 catkin_package的配置

  1. 官方声明为catkin specific configuration;即可以理解为find_package在执行时候需要的依赖项文件;
  2. 其中内容按照关键字包括①INCLUDE_DIRS include 其他文件夹位置②LIBRARIES 功能包名③ CATKIN_DEPENDS 执行依赖项例如message_runtime④DEPENDS system_lib 其他系统库文件夹

图片.png

2.3.1.5 include_package配置

  1. 官方声明为指定头文件的附加位置,功能包的位置应该在其他位置之前就应该列出;
  2. 例如include_directories(${catkin_INCLUDE_DIRS})其实也等价于当前功能包下的include文件夹即include_directories(include)

图片.png

2.3.1.6 C++编译配置

  1. 声明一个 C++ 库:add_library(${PROJECT_NAME} src/${PROJECT_NAME}/功能包名.cpp)
  2. 添加库的cmake目标依赖,主要正对于自定义消息或者是ROS动态重配置参数,解决本功能包编译时候,如果需要其他依赖的功能包但是没有编译的一个顺序依赖问题:add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
  3. 声明一个 C++ 可执行文件: add_executable(${PROJECT_NAME}_node src/目标代码文件.cpp)
  4. 指定库以链接库或可执行目标:target_link_libraries(${PROJECT_NAME}_node ${catkin_LIBRARIES})

图片.png

2.3.1.7 Python配置

例如:catkin_install_python(PROGRAMS scripts/目标代码.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})

图片.png

2.3.1.8 参考文献

ROS-WIKI:catkinCMakeLists.txt

2.3.2 package.xml文件解读

解读package.xml主要对其构建、运行和测试依赖项(Build, Run, and Test Dependencies)进行分析,这些依赖项即最小的、不依赖其他功能包的包,例如std_msgs、roscpp和rospy这样的,这些包可以有以下几种类型:

    1. Build Dependencies(<build_depend>) :指定构建这个包需要哪些包,其包括这些包的头文件,链接来自这些包的库或在构建时需要其他资源(尤其是当这些包在CMake中使用find_package()时)。
    1. Build Export Dependencies(<build_export_depend>) :指定需要哪些包来对这个功能包构建库。例如,当将它们的头文件传递包含在公共头文件中时,尤其是当这些包在CMake的catkin_package()中声明为 (CATKIN_)DEPENDS时。
    1. Execution Dependencies(<exec_depend>) :指定运行此包中的代码需要哪些包。例如,赖此包中的共享库时,尤其当这些包在CMake中的catkin_package()中声明为(CATKIN_)DEPENDS时。
    1. Test Dependencies(<test_depend>) :仅指定单元测试的附加依赖项。这一项不应该使用任何已经作为构建或运行依赖项的依赖项。
    1. Build Tool Dependencies(<buildtool_depend>) :指定此包需要自行构建的构建系统工具。在ROS中,一般而言catkin是唯一的构建工具。
    1. Documentation Tool Dependencies(<doc_depend>) :指定此包生成文档所需的文档工具。
    1. Run Dependencies(<run_depend>) :指定运行此包中的代码需要哪些包,或针对此包构建库。类似于Execution Dependencies(<exec_depend>),当依赖共享库(shared libraries)或将它们的头文件传递地包含在此包的公共头文件中时,尤其是当这些包在CMake中的catkin_package()中声明为 (CATKIN_)DEPEND。

参考文献:ROSWIKI-package.xml

2.4 服务通讯编程

2.4.1 服务通讯理论模型

服务通讯的理论模型如图所示,主要由以下五步骤组成。

图片.png

  • ①Server注册:Server 启动后,会通过RPC在 ROS Master 中注册自身信息,其中包含提供的服务的名称。ROS Master 会将节点的注册信息加入到注册表中。

  • ②Client注册:Client 启动后,也会通过RPC在ROS Master 中注册自身信息,包含需要请求的服务的名称。ROS Master 会将节点的注册信息加入到注册表中。

  • ③ROS Master实现信息匹配:ROS Master会根据注册表中的信息匹配Server和Client,并通过 RPC向Client发送 Server的TCP地址。

  • ④Client发送请求:Client 根据步骤2 响应的信息,使用 TCP 与 Server 建立网络连接,并发送请求数据。

  • ⑤Server发送响应:Server 接收、解析请求的数据,并产生响应结果返回给 Client。

注意:与话题通讯的具有很大的区别,Server必须在Client前面启动

2.4.2 服务通讯的基本编程

服务通讯编程,其实是为自定义服务消息进行编程使用,其步骤和自定义消息类型的话题编程类似。

  • 服务编程的基本内容:编写两个节点,一个作为客户端,一个作为服务端,服务端在命令行发布两个数字给服务端,服务端实现求和之后返回给客户端。

  • 下面的代码Github连接:topic_communication

2.4.2.1 编写srv服务文件

    1. 新建功能包;在工作空间下新建功能包service_communication,依赖项包括std_msgs roscpp rospy等基础项目。

图片.png

    1. 创建文件夹目录,在service_communication功能包下面,创建文件夹srv和文件夹scripts分别用于存放服务文件和Python文件。
ubuntu@ubuntu:~/catkin_ws/src/service_communication$ tree
.
├── CMakeLists.txt
├── include
│   └── service_communication
├── package.xml
├── scripts
├── src
└── srv

5 directories, 2 files
    1. ** 编写服务文件**。在srv文件夹下新建自定义服务文件AddTwoInt.srv用于实现服务程序两数求和,前俩行的a和b表示服务端的请求数据,---号表示分割,c表示服务端的应答数据,此时的a,b和c只是指代请求端(request)和响应端的数据类型(respond),没有任何操作功能。
catkin_ws/src/service_communication/srv/AddTwoInt.srv
# 客户端请求时发送的两个数字
int32 a
int32 b
---
# 服务器响应发送的数据
int32 c

2.4.2.2 配置自定义服务文件

同理,配置srv文件包括在package.xmlCMakeList.txt配置两部分。

    1. 在功能包的package.xml里添加话题的依赖,这一步操作和自定义消息配置是一样的。即在service_communication文件夹的package.xml里添加:
<exec_depend>message_runtime</exec_depend>
<build_depend>message_generation</build_depend>
    1. 在功能包的CmakeLists.txt添加编译选项,此时和自定义消息也是一样的,包括四部分
    • 5.1. 添加编译依赖项功能包find_package(catkin REQUIRED COMPONENTS ..+ 依赖项功能包),大约在第10行,此时依赖项功能包名字为message_generation(build_depend的内容),而且必须有std_msgs作为基础在里面,配置的内容如下所示:
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
    • 5.2 . 添加自定义srv文件add_service_files(FILES 文件名),大约在第58行,如此时的文件名为AddTwoInt.srv:
add_service_files(
   FILES
   AddTwoInt.srv
)
    • 5.3. 添加srv的编译依赖项generate_messages(DEPENDENCIES std_msgs),大约在第71行,即表示在编译msg时候得依赖于std_msgs
generate_messages(
  DEPENDENCIES
  std_msgs
)
    • 5.4. 添加执行时的依赖:catkin_package的关键字CATKIN_DEPENDS后+包,大约在106行,在官网上,并没有要求执行这一步,但是为了规范加上这一步,即:
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES service_communication
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)

2.4.2.3 编译自定义服务文件并查看中间文件

    1. 编译功能包,在工作空间catkin_ws下执行catkin_make编译功能包,编译成功后,查看中间文件。同样的C++的中间文件在/home/ubuntu/catkin_ws/devel/include/功能包名/文件夹下Python的中间文件在/home/ubuntu/catkin_ws/devel/lib/python2.7/dist-packages/功能包名/srv文件夹

图片.png

2.4.2.4 编译C++代码调用自定义服务

    1. 创建C++服务端程序,并在CMakeList.txt配置C++文件
    • 7.1. 创建客户端程序。创建客户端程序clientc_cpp.cpp。此时额外注意如果客户端比服务器提前启动的解决办法!!client.waitForExistence()!

catkin_ws/src/service_communication/src/client_cpp.cpp

/**
 * AddTwoInt Client
 */
#include <cstdlib>
#include "ros/ros.h"
#include "service_communication/AddTwoInt.h"

int main(int argc, char **argv)
{
  setlocale(LC_ALL,"");
  // ROS节点初始化
  ros::init(argc, argv, "add_two_ints_client");
  
  // 从终端命令行获取两个加数
  if (argc != 3)
  {
    ROS_INFO("usage: add_two_ints_client X Y");
    return 1;
  }
  // 创建节点句柄
  ros::NodeHandle n;
    // 创建一个client,请求add_two_int service,service消息类型是service_communication::AddTwoInt
  ros::ServiceClient client = n.serviceClient<service_communication::AddTwoInt>("add_two_ints");
   // 创建service_communication::AddTwoInt类型的service消息
  service_communication::AddTwoInt srv;
  srv.request.a = atoll(argv[1]);
  srv.request.b = atoll(argv[2]);
    // 发布service请求,等待加法运算的应答结果
    // 等待客户端启动
  client.waitForExistence();
    // 也可以采用代码ros::service::waitForService("AddTwoInt");

  if (client.call(srv))
  {
    ROS_INFO("c: %ld", (long int)srv.response.c);
  }
  else
  {
    ROS_ERROR("客户端没有启动");
    return 1;
  }

  return 0;
}
    • 7.2. 在功能包的src目录下,创建服务程序server_cpp.cpp。

catkin_ws/src/service_communication/src/server_cpp.cpp

/**
 * AddTwoInt Server
 */
 
#include "ros/ros.h"
#include "service_communication/AddTwoInt.h"

// service回调函数,输入参数req,输出参数res
bool add(service_communication::AddTwoInt::Request  &req,
         service_communication::AddTwoInt::Response &res)
{
  // 将输入参数中的请求数据相加,结果放到应答变量中
  res.c = req.a + req.b;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
  ROS_INFO("sending back response: [%ld]", (long int)res.c);
  
  return true;
}

int main(int argc, char **argv)
{
  // ROS节点初始化
  ros::init(argc, argv, "add_two_ints_server");
  
  // 创建节点句柄
  ros::NodeHandle n;

  // 创建一个名为add_two_ints的server,注册回调函数add()
  ros::ServiceServer service = n.advertiseService("add_two_ints", add);
  
  // 循环等待回调函数
  ROS_INFO("Ready to add two ints.");
  ros::spin();

  return 0;
}

    • 7.3. 配置功能包下的CMakeLists.txt文件,和自定义消息话题通讯一样,也包括add_executableadd_dependenciestarget_link_libraries三项。注意与自定义消息话题通讯区别在于add_dependencies的参数

catkin_ws/src/service_communication/CMakeLists.txt

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

add_executable(client src/client_cpp.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp
    • 7.4. 在工作空间进行编译;
    • 7.5. 运行服务编程。首先打开一个终端输入roscore,打开ROS,再新建一个终端输入先rosrun service_communication server运行服务程序。最后新建终端输入rosrun service_communication client 1 2即运行客户端并执行1和2的加法操作。

图片.png

2.4.2.5 编译Python代码调用自定义服务

    1. 在scripts文件夹编写Python代码,同时赋予可执行权限。
    • 8.1. 编写Python的客户端代码client_py.py代码,同样注意这个服务器是否没有启动的优化。

catkin_ws/src/service_communication/scripts/client_py.py

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

#1.导包
import rospy
from service_communication.srv import *
import sys

if __name__ == "__main__":

    #优化实现
    if len(sys.argv) != 3:
        rospy.logerr("请正确提交参数")
        sys.exit(1)


    # 2.初始化 ROS 节点
    rospy.init_node("AddTwoInt_Client_p")
    # 3.创建请求对象
    client = rospy.ServiceProxy("AddTwoInt",AddTwoInt)
    # 请求前,等待服务已经就绪

    client.wait_for_service()
    # 4.发送请求,接收并处理响应

    req = AddTwoIntRequest()
    req.a = int(sys.argv[1])
    req.b = int(sys.argv[2]) 

    resp = client.call(req)
    rospy.loginfo("响应结果:%d",resp.c)

    • 8.2. 编写Python的服务器server_py.py代码:

catkin_ws/src/service_communication/scripts/server_py.py

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

# 1.导包
import rospy
from service_communication.srv import *
# 回调函数的参数是请求对象,返回值是响应对象
def doReq(req):
    # 解析提交的数据
    c = req.a + req.b
    rospy.loginfo("提交的数据:a = %d, b = %d, c = %d",req.a, req.b, c)

    # 创建响应对象,赋值并返回
    # resp = AddTwoIntResponse()
    # resp.c = c
    resp = AddTwoIntResponse(c)
    return resp


if __name__ == "__main__":
    # 2.初始化 ROS 节点
    rospy.init_node("AddTwoInt_server_p")
    # 3.创建服务对象
    server = rospy.Service("AddTwoInt",AddTwoInt,doReq)
    # 4.回调函数处理请求并产生响应
    # 5.spin 函数
    rospy.spin()
    • 8.3. 给Python文件赋予可执行权限,在script文件夹下输入命令sudo chmod +x *.py即可赋予所有Python可执行权限。
    • 8.4. 先roscore打开ROS,再输入rosrun service_communication server_py.py即可运行py文件,同理运行client_py.py文件,其中未按照要求输入会提示No handlers could be found for logger "rosout"

图片.png

2.4.3 服务通讯编程总结

服务通讯的关键点主要在于理解其作用:请求响应模式实现不同节点之间数据交互,用于偶然的、对时时性有要求、有一定逻辑处理需求的数据传输场景

同时理解服务通讯理论模型的五个步骤,即服务端的启动是需要在客户端之前的,以及在编写代码时候对启动先后的处理

2.4.3.1 服务通讯流程

服务通讯的操作流程和自定义消息话题通讯是类似的,主要包括:

  1. 在srv文件夹编写自定义srv文件,配置package.xml文件包括①exec_depend>message_runtime</exec_depend>②<build_depend>message_generation</build_depend>
  2. 配置CMakeList.txt文件包括①添加编译依赖项功能包:find_package;②添加自定义msg文件:add_message_files;③添加msg的编译依赖项:generate_messages;④添加执行时的依赖:catkin_package;
  3. C++代码:①添加头文件(头文件为功能包名字/自定义服务名.h);②正常编写代码;③CMakeList.txt进行配置(不仅有add_executable和target_link_libraries还包括add_dependencies);④编译运行;
  4. Python代码:①添加包,from 功能包名.srv import *;②正常代码编写;②CMakeList.txt进行配置(目前配置不配置影响不大);③赋予py文件可执行权限;④编译运行。

2.4.3.2 服务编程代码逻辑

图片.png

2.4.3.3 参考文献

B站视频:【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程

ROS-WIKI:编写简单的服务和客户端(C++)

ROS-WIKI:编写简单的服务和客户端(Python)

ROS-WIKI:检验简单的服务和客户端

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

2 ROS1通讯编程基础(2) 的相关文章

随机推荐

  • 队列的应用之打印杨辉三角形

    题目 xff1a 利用队列打印杨辉三角形 特点 xff1a 杨辉三角除第一行为两个1以外 xff0c 从第二行开始 xff0c 每一行的首尾都为1 xff0c 中间位置的数为上一行中与之相邻的两个数之和 xff0c 可以使用我们学过的队列问
  • 栈和队列的应用之停车问题

    题目 xff1a 设停车场是一个可停放n辆汽车的狭长通道 xff0c 且只有一个大门可供汽车进出 汽车在停车场内按车辆到达时间的先后顺序 xff0c 依次由北向南排列 xff08 大门在最南端 xff0c 最先到达的第一辆车停放在停车场的最
  • Jupyter Notebook 安装与使用教程

    一 什么是Jupyter Notebook xff1f 1 简介 Jupyter Notebook是基于网页的用于交互计算的应用程序 其可被应用于全过程计算 xff1a 开发 文档编写 运行代码和展示结果 Jupyter Notebook官
  • java.lang.NoSuchMethodError: org.springframework.core.type.AnnotationMetadata.introspect之解决方法

    错误 xff1a idea中使用spring整合mybatis报错 xff1a java lang NoSuchMethodError org springframework core type AnnotationMetadata int
  • 栈和队列的应用之回文数判断

    题目 xff1a 采用栈和队列的方法检测并输出一个单词是否为回文 代码 xff1a include lt stdio h gt include lt malloc h gt define SIZE 20 using namespace st
  • 二叉链表树的遍历

    题目 xff1a 使用二叉链表树创建算法Status CreatBiTree BiTree amp T 和其他代码 二叉树的遍历有三种 xff1a 前序遍历 xff1a 先访问根节点 xff0c 再遍历左子树 xff0c 最后遍历右子树 x
  • opencv的框架与各模块功能介绍

    记录一下自己的所学知识 xff0c 便于日后回顾与整理 文中内容多为摘录 xff0c 具体链接如下 xff1a 摘录自 xff1a https zhuanlan zhihu com p 33008701 xff08 框架介绍 xff09 h
  • Android调用C/C++库

    AndroidStudio版本2021 1 1 一 AndroidStudio将C C 43 43 库打包成so库过程 AndroidStudio新建NativeC 43 43 工程 xff1b 在Tools gt SDK Manager里
  • SocketCan 应用编程

    SocketCan 应用编程 由于 Linux 系统将 CAN 设备作为网络设备进行管理 xff0c 因此在 CAN 总线应用开发方面 xff0c Linux 提供了SocketCAN 应用编程接口 xff0c 使得 CAN 总线通信近似于
  • QT开发笔记(继承 QObject 的线程 )

    继承 QObject 的线程 在第 10 章章节开头已经说过 xff0c 继承 QThread 类是创建线程的一种方法 xff0c 另一种就是继承 QObject 类 继承 QObject 类更加灵活 它通过 QObject moveToT
  • CoppeliaSim:视觉传感器的使用与属性参数

    视觉传感器类型 http www coppeliarobotics com helpFiles index html Orthographic projection type the field of view of orthographi
  • 华为Atlas200DK环境配置指南(版本20.0.0)

    官方参考文档 https support huaweicloud com usermanual A200dk 3000 atlas200dk 02 0024 html 务必保证配置时版本 20 0 0 一致 1 配置开发环境 自己电脑 若不
  • PX4 QGC地面站自定义参数

    QGC地面站自定义参数 xff08 新手操作 xff09 v1 8 2 QGC以往版本下载地址 htps github com mavlink qgroundcontrol tags 最终的添加结果如下 xff1a 具体步骤如下 xff1a
  • Linux网络编程----UDP编程基础知识

    UDP概述 UDP 是 User Datagram Protocol 的简称 xff0c 中文名是用户数据报协议 xff0c 是一个简单的面向数据报的传输层协议 xff0c 在网络中用于处理数据包 xff0c 是一种无连接的协议 UDP 不
  • get 命令汇总

    get 命令汇总 git config 配置 Git 的相关参数 Git 一共有3个配置文件 xff1a 1 仓库级的配置文件 xff1a 在仓库的 git gitconfig xff0c 该配置文件只对所在的仓库有效 2 全局配置文件 x
  • c++ socket简单封装

    简单封装 并不实际应用 框架图 Mysocket 主要是定义TCP和UDP的一些相同的操作 xff0c 需要的他们各自去实现 Mysocket h ifndef MYSOCKET H define MYSOCKET H class MySo
  • pixhawk2飞控接头型号

    BM04B GHS TBT BM05B GHS TBT BM06B GHS TBT
  • 多种视觉SLAM方案对比

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 本文转自 新机器视觉 在SLAM研究中 xff0c 我们通常需要在各数据集上测试各个方案的性能情况 如下主要对表1中6个视觉SLAM方
  • 激光雷达核心技术及行业格局梳理

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 引言 xff1a 车载摄像头是ADAS 的核心传感器 车载摄像头搭载颗数稳步提升 根据 Yole 数据 xff0c 2018 年全球平
  • 2 ROS1通讯编程基础(2)

    2 ROS1通讯编程基础 2 3 配置文件的解读2 3 1 CMakeList txt解读2 3 1 1 find package的配置2 3 1 2 messages services and actions的配置2 3 1 3 动态重配