1.3 ROS学习笔记之服务I

导览

你将从本单元学到:

什么是服务?
如何管理一个机器人的服务?
如何调用一个服务?

课前总结

  • 主题是棍棒,服务是屠龙刀
  • 调用服务(如人脸识别),一直等待,直到服务完成
  • 调用行为(某种方式移动机器人),可并行执行其他行为,且可以接收移动中的反馈
  • 查看所有可用的服务: rosservice list
  • 获取服务的信息:rosservice info /name_of_your_service
  • 调用服务: rosservice call /gazebo/delete_model “model_name: ‘cafe_table’ 服务名+参数
  • 获取场景中的对象列表: rostopic echo /gazebo/model_states -n1
  • 查看服务的相关信息(提供服务的节点,使用的信息类型,调用服务时参数):rosservice info /name_of_the_service
  • 查看服务消息结构:rossrv show name_of_the_package/Name_of_Service_message
  • 节点提供服务,节点调用服务

服务概述

使用主题,你差不多就可以做自己想做的的任何事情。很多ROS功能包仅用到了主题就可以完美地工作。

那么,为什么还需要学习 服务 呢?
在某些情况下,主题是不够的,或者使用起来太过麻烦。当然,你可以使用一根棍棒毁掉 死星,但需要花费很长很长时间。更好的办法是,让天行者卢克替你去做这件事情,对吧?服务的作用正是如此,它们使工作变得更加简单

服务行为主题辨析

理解服务的概念和用法,必须把服务和主题与行为进行比较。

假设你有个自己的BB-8机器人,它有一个激光传感器,一套人脸识别系统和一个导航系统。激光传感器将向一个主题,以20HZ的频率发布数据。我们使用主题是因为我们需要使它发布的那些信息时刻能被其他ROS系统(比如导航系统)使用。

人脸识别系统将提供一个 服务。你的ROS程序将调用该服务,然后一直等着,直到识别系统告诉你BB-8前面所站着的人的姓名。

导航系统将提供一个 行为。你的ROS程序将调用该行为使机器人移动,并且当它在执行该任务时,你的程序还可以执行其他任务,比如抱怨C-3P0是多么的辛苦。行为会在移动的过程中给你 反馈 信息(例如,距离期望坐标的距离)

服务与行为(同步异步)

服务是 同步的。当你的程序调用一个服务时,从服务接收到一个结果前你的程序不能再做其他事情。
行为是 异步的。就像启动了一个新线程。当你的ROS程序调用一个行为时,你的程序可以在该行为被执行的同时在另一线程执行其他任务。

当你的程序从服务接收到结果前不需要执行其他任务时,使用服务

服务实例(启动服务)

使用一个launch文件启动多个节点

第一个节点提供 服务。 该节点是包含该服务的节点。
第二个节点调用该服务。当该服务被调用时,机器人将按给定的轨迹执行

查看所有可用的服务列表

rosservice list
有很多服务,其中一些是仿真器系统 (/gazebo/…)提供的, 其他的是Kinect Camera (/camera/…) 和机器人本身(/iri_wam/…)提供的

获取关于服务的信息

rosservice info /name_of_your_service

user ~ $ rosservice info /execute_trajectory
Node: /iri_wam_reproduce_trajectory
URI: rosrpc://ip-172-31-17-169:35175
Type: iri_wam_reproduce_trajectory/ExecTraj
Args: file

各参数意义如下:

Node: 表示提供(或创建)该服务的**节点**。
Type: 指该服务使用的**消息类型**。其结构与主题相同。通常由 package_where_the_service_message_is_defined / Name_of_the_File_where_Service_message_is_defined 构成。该例中,功能包是 iri_wam_reproduce_trajectory,定义服务消息的文件名为 ExecTraj。
Args:  从这里可以找到该服务被调用时所使用的参数。该例中,只有一个参数 trajectory file path ,该参数存储在一个名为file 的变量中。

服务是如何开始的?
下面是一个通过WebShell查看 start_demo.launch 文件的例子

查看launch文件

你还记得如何直接进入一个功能包吗?你还记得从哪里可以找到launch文件吗?

roscd iri_wam_aff_demo
cd launch/
cat start_demo.launch
<launch>

  <include file="$(find iri_wam_reproduce_trajectory)/launch/start_service.launch"/>

  <node pkg ="iri_wam_aff_demo"
        type="iri_wam_aff_demo_node"
        name="iri_wam_aff_demo"
        output="screen">
  </node>

</launch>

1) 该launch文件的第一部分调用另一个名为 start_service.launch 的launch文件

start_service.launch文件启动提供/execute_trajectory 服务的节点。注意,它使用一个特殊的ROS launch文件函数查找指定功能包的路径。

2) 该launch文件的第二部分启动一个你刚在ROS Basics Unit学习过的节点。该节点调用 /execute_trajectory 服务来使机器人移动。

3) 第二个节点不是一个Python节点,而是一个编译过的cpp节点(二进制)。你既可以用CPP也可以用Python来构建ROS程序。该课程主要使用Python。

<node pkg ="package_where_cpp_is"
      type="name_of_binary_after_compiling_cpp"
      name="name_of_the_node_initialised_in_cpp"
      output="screen">
</node>

服务实例(调用服务)

可以从控制台手动调用一个服务。这有助于测试,还有助于理解服务是如何工作的

rosservice call /the_service_name TAB-TAB

TAB-TAB表示快速按 TAB 键两次。它会自动完成将被发送的服务消息。接着,你只需把值填上即可

当你快速按下 [TAB]两次后,出现一个额外的信息。ROS自动补全输入,补全请求该服务的结构。
本例中,它给出下面的结构:

“model_name: ‘the_name_of_the_object_you_want_to_delete’”

/gazebo/delete_model 是一个由Gazebo仿真器提供的服务, 检测场景中的任何对象。

使用该服务来移除桌子。在该仿真中桌子的model_name是cafe_table

rosservice call /gazebo/delete_model “model_name: ‘cafe_table’

获取场景中的对象列表

若想对仿真中的任何对象进行操作的话,你必须学会如何获取场景中的对象列表

rostopic echo /gazebo/model_states -n1

程序与服务交互

#! /usr/bin/env python

import rospy
from gazebo_msgs.srv import DeleteModel, DeleteModelRequest # 导入服务 /gazebo/delete_model使用的服务消息
import sys 

rospy.init_node('service_client') # 初始化一个名为 service_client的ROS节点
rospy.wait_for_service('/gazebo/delete_model') # 等待服务客户端 /gazebo/delete_model 运行
delete_model_service = rospy.ServiceProxy('/gazebo/delete_model', DeleteModel) # 创建与服务的连接
kk = DeleteModelRequest() # 创建一个类型为 DeleteModelRequest的对象
kk.model_name = "bowl_1" # 为该对象的model_name变量赋值
result = delete_model_service(kk) # 通过连接,发送要被服务删除的对象名称
print result # 打印被调用的服务给出的结果

查看服务使用的消息结构

  • 使用 rosservice info 命令可以查看服务所使用的消息类型
    rosservice info /name_of_the_service
    返回 name_of_the_package/Name_of_Service_message

  • 查看该服务使用消息的结构
    rossrv show name_of_the_package/Name_of_Service_message

输出

user catkin_ws $ rossrv show gazebo_msgs/DeleteModel
string model_name
---
bool success
string status_message
  • 服务消息包括请求和响应
  • 对于DeleteModel 服务这个例子, 请求 包含了一个名为 model_name 的字符串, 响应 则由一个名为 success 的布尔值和一个名为 status_message 的字符串组成。

  • 服务消息中每部分元素的数量各不相同,具体数量取决于所需要的服务。如果你觉得它与你的服务不相关,你甚至可以把它设置成“无”。消息中最重要的部分是三个破折号—, 它们表示该消息的类型为服务消息。

1 - 服务消息文件扩展名为 .srv。主题消息扩展名为 .msg
2 - 服务消息文件定义在一个 srv 目录中。主题消息文件定义在一个 msg 目录中。

查看所有服务消息

roscd gazebo_msgs; ls srv

  • 请求 是服务消息中定义 如何调用服务 的那一部分。它给出了你必须向消息服务器传送哪些变量才能使它开始任务。

  • 响应 是服务消息中定义完成任务后 你的服务如何响应 的那一部分。例如,如果一切运行正常,它将返回一个带有特定消息的字符串;如果运行错误,它将什么都不返回

总结

  • 服务为其他程序提供特定功能。如果一个节点知道如何在仿真中删除一个对象,那么它可以通过一个服务为其他节点提供该功能,以便其他节点需要删除对象时调用该服务

练习

待补
- 当你启动一个同名的新节点时,有时它会结束前面的那个节点。好的做法是手动结束而不是依赖系统来结束旧的节点
- 使用Web控制台编辑器vim查看一下这些trajectory_files 中的一个,或者拷贝至我们的工作空间 /home/user/carkin_ws/src,你将会明白它们是如何工作的。 让我们查看一下get_food.txt文件
- 服务execute_trajectory 将基于调用中给出的路径读取上面这些值(调用时指定轨迹文件,从而读取相应值)

猜你喜欢

转载自blog.csdn.net/lwz45698752/article/details/81515059
1.3
今日推荐