• [ROS](10)ROS通信 —— 服务(Service)通信


      文章只是个人学习过程中学习笔记,主要参考ROS教程1


    1、概念

      服务(Services):是节点之间通讯的另一种方式。服务允许节点发送一个请求(request)并获得一个响应(response)。
    service概念图.png

    图1-1 服务(Services)、服务客户端(Client)和服务服务器(Server)的概念图

    2、 服务通信机制

      服务通信 是也是ROS通信中最常用的一种基于 请求和响应 模型的通信方式。用于临时性、非周期性、有一定逻辑处理的数据传输场景。

       服务通信 通过允许请求-响应通信来实现更紧密的耦合。服务客户端向服务服务器发送请求消息并等待响应(客户端将阻塞,直到收到响应)。服务器将使用请求中的数据构造响应消息并将其发送回客户端。每个服务都有一个类型,它决定了请求和响应消息的结构。服务也有在一个网络中唯一的名称。

      ROS Node想通过service方式来传递消息: 首先Server节点和Client节点都要到ROS Master(节点管理器)中进行注册节点名称、服务(Sevice)名称、消息类型、URI地址和端口;然后, ROS Master会根据注册表中的信息匹配Server Client,并向Client发送 Server 的 TCP 地址信息;其次,Client 根据Server的信息,使用TCP与Server 建立连接,并请求发送消息;最后, Server 接收、解析请求的数据,并产生响应结果返回给 Client

    sevice通信架构.png

    图2-1 服务(Services)通信模型

    1.客户端请求被处理时,需要保证服务器已经启动;
    2.服务端和客户端都可以存在多个;

    3、服务命令rosservice

    rosservice 2 可以很容易地通过服务附加到ROS客户端/服务器框架上。

    命令功能
    rosservice argc输出服务的参数
    rosservice call用给定的参数调用服务
    rosservice find按服务的类型查找服务
    rosservice info输出服务的信息
    rosservice list输出活跃的服务
    rosservice type输出服务的类型
    rosservice uri输出服务的ROSRPC uri

    Tips:使用rosservice -h 帮助选项获取更详细的用法。

    4、服务通信实操 – 在乌龟模拟器的指定位置孵化一个小乌龟

      通过ROS内置的乌龟模拟器turtlesim)来进行服务通信的实操,在乌龟模拟器的指定位置孵化一个小乌龟。
      实现的步骤如下:
      步骤1:在新终端中启动roscore

    roscore
    
    • 1

      步骤2:在新终端中启动乌龟模拟器节点turtlesim_node

    rosrun turtlesim turtlesim_node
    
    • 1

      步骤3:通过调试工具rqt_service_caller和编程的方式在乌龟模拟器的指定位置孵化一个小乌龟。

    4.1 调试工具实现

      通过rqt_service_caller工具模拟服务请求:

    • 启动rqt_service_caller工具
    rosrun rqt_service_caller rqt_service_caller
    
    • 1
    • 通过图形化配置参数,如果所示,选择孵化服务 /spawn,在Request中配置孵化位置、角度、乌龟名字请求参数,然后点击右上角call 发送请求,如果乌龟模拟器响应成功,会在Response中显示结果,并在乌龟模拟器turtlesim中孵化出一个小乌龟。

    service rqt_service_caller.png

    图4-1 使用rqt_service_caller工具模拟服务请求

    4.2 编程实现(C++)

      在beginner_tutorials软件包的src目录下创建服务客户端源文件:

    roscd beginner_tutorials
    cd src
    touch turtle_spawn_client.cpp
    
    • 1
    • 2
    • 3

    4.2.1 服务客户端程序(turtle_spawn_client.cpp)

    #include "ros/ros.h"
    #include "turtlesim/Spawn.h"
    
    int main(int argc, char **argv)
    {
        setlocale(LC_ALL,"");
    
        /* 初始化ROS节点 */
        ros::init(argc,argv,"turtle_spawn_client");
        /* 为这个节点创建句柄 */
        ros::NodeHandle nh;
        /* 创建service client 指定服务类型为turtlesim::Spawn */
        ros::ServiceClient client = nh.serviceClient<turtlesim::Spawn>("/spawn");
    
        /* 等待服务器启动 */
        ros::service::waitForService("/spawn");
        
        /* 实例化服务数据类型,并给成员request赋值 */
        turtlesim::Spawn spawn;
        spawn.request.x = 2;
        spawn.request.y = 8;
        spawn.request.theta = 1.8;
        spawn.request.name = "new_turtle1";
    
        /* 服务调用 */
        if(client.call(spawn))
        {
            ROS_INFO("小乌龟[%s]已孵化", spawn.response.name.c_str());
        }
        else
        {
            ROS_INFO("小乌龟孵化失败!");
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    4.2.2 配置CMakeLists.txt

      只需将这几行添加到CMakeLists.txt文件的底部:

    add_executable(turtle_spawn_client src/turtle_spawn_client.cpp)
    target_link_libraries(turtle_spawn_client ${catkin_LIBRARIES})
    add_dependencies(turtle_spawn_client ${PROJECT_NAME}_gencpp)
    
    • 1
    • 2
    • 3

    4.2.3 编译、运行

    在你的工作空间下执行catkin_make编译,将turtle_spawn_client.cpp编译成可执行文件turtle_spawn_client。编译后,在终端中执行过程如下所示。
    sevice turtlesim spawn.png

    图4-2 运行服务客户端 turtle_spawn_client,孵化小乌龟(左上)

    4.3 编程实现(Python)

      在beginner_tutorials软件包的scripts目录下创建服务客户端源文件:

    roscd beginner_tutorials
    cd scripts
    touch turtle_client.py
    chmod +x turtle_client.py
    
    • 1
    • 2
    • 3
    • 4

    4.3.1 服务客户端程序(turtle_spawn_client.py)

    #!/usr/bin/env python
    # encoding: utf-8
    
    import rospy
    from turtlesim.srv import Spawn,SpawnRequest
    
    def turtle_spawn_client():
        # 初始化ROS节点
        rospy.init_node("turtle_spawn_client")
        # 创建sevice client
        spawn_client = rospy.ServiceProxy('/spawn',Spawn)
    
        # 等待服务开启
        spawn_client.wait_for_service()
    
        # 创建请求数据
        spawn_req = SpawnRequest()
        spawn_req.x = 8.0
        spawn_req.y = 8.0
        spawn_req.theta = 0.8
        spawn_req.name = "new_turtle2"
    
        try:     
            # 调用服务并获取相应结果
            spawn_res = spawn_client.call(spawn_req)    
            rospy.loginfo("小乌龟[%s]龟已孵化", spawn_res.name)
        except rospy.ServiceException as e:
            rospy.loginfo("小乌龟孵化失败!")    
    
    if __name__ == '__main__':
        turtle_spawn_client()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    4.2.2 配置CMakeLists.txt

      只需catkin_install_python中添加 scripts/turtle_spawn_client.py即可:

    # 安装python可执行脚本
    catkin_install_python(PROGRAMS
      scripts/turtle_spawn_client.py
      ... 
      DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
      )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.2.3 编译、运行

      其实这个例子很简单,不需要编译,直接执行python文件就行。但是我们还是养成习惯吧,每次创建和修改代码后,就catkin_make编译一下,即使是Python节点也必须使用它。这是为了确保能为创建的消息和服务自动生成Python代码。
    sevice turtlesim spawn 2.png

    图4-3 运行服务客户端 turtle_spawn_client.py,孵化小乌龟(右上)

    5、服务命令实操

      ROS提供了一些命令行工具帮助我们查看Service的信息。通过小乌龟模拟器(turtlesim)来实操服务命令。

    5.1 rosservice list

       rosservice list 输出活跃(当前正在运行)服务的信息。

    rosservice list.png

       list命令显示有两个与rosout节点有关的服务:/rosout/get_loggers和/rosout/set_logger_level。其余的都是turtlesim节点提供了9个服务。

    5.2 rosservice argc

       rosservice argc[service] 输出服务的所有参数。

    rosservice argc.png

    5.3 rosservice type

       rosservice type [service] 输出服务的类型。

    rosservice type.png

    5.4 rosservice find

       rosservice call [service] 按服务的类型查找服务。
    rosservice find

    5.5 rosservice uri

       rosservice uri 输出服务的ROSRPC uri。

    在这里插入图片描述

    5.6 rosservice info

       rosservice info [service] 输出服务的信息。
    rosservice info

    5.7 rosservice call

       rosservice call [service] [args] 用给定的参数调用服务。

    # 调用服务 /spawn ,给定参数:位置(8.0,2.0)、角度为1.8、名字为new_turtle3,然后孵化小乌龟。
    rosservice call /spawn  8.0 2.0 1.8 "new_turtle3"
    
    • 1
    • 2

    rosservice call

    图4-3 运行 rosservice call 命令,孵化小乌龟(右下)

    1. ROS.otg. ROS教程[EB/OL]. 2020-12-22[2022-7-5].
      http://wiki.ros.org/cn/ROS/Tutorials. ↩︎

    2. ROS.otg. rosservice[EB/OL]. 2020-12-22[2022-7-5].
      https://wiki.ros.org/rosservice. ↩︎

  • 相关阅读:
    MySQL用户管理(创建、修改、删除用户)
    Linux 文件/目录访问(opendir/closedir/readdir)
    最新定制的安卓项目及设计报告——仿番茄小说APP
    【操作系统笔记十二】Linux常用基础命令
    六、python Django REST framework增删改查[视图、扩展类、扩展类的子类、视图集]
    db-cdc之mysql 深入了解并使用binlog
    Kubernetes 深入理解Kubernetes(二) 声明组织对象
    net-java-php-python-校园二手图书销售网站计算机毕业设计程序
    姓氏起源查询易语言代码
    js——高阶函数、闭包、递归以及浅拷贝和深拷贝
  • 原文地址:https://blog.csdn.net/CynalFly/article/details/126055496