文章只是个人学习过程中学习笔记,主要参考ROS教程1。
1、概念
服务(Services
):是节点之间通讯的另一种方式。服务允许节点发送一个请求(request)并获得一个响应(response)。
2、 服务通信机制
服务通信
是也是ROS通信中最常用的一种基于 请求和响应
模型的通信方式。用于临时性、非周期性、有一定逻辑处理的数据传输场景。
服务通信
通过允许请求-响应通信来实现更紧密的耦合。服务客户端向服务服务器发送请求消息并等待响应(客户端将阻塞,直到收到响应)。服务器将使用请求中的数据构造响应消息并将其发送回客户端。每个服务都有一个类型,它决定了请求和响应消息的结构。服务也有在一个网络中唯一的名称。
ROS Node想通过service
方式来传递消息: 首先Server
节点和Client
节点都要到ROS Master(节点管理器)中进行注册节点名称、服务(Sevice)名称、消息类型、URI地址和端口;然后, ROS Master会根据注册表中的信息匹配Server
和 Client
,并向Client
发送 Server
的 TCP 地址信息;其次,Client
根据Server
的信息,使用TCP与Server 建立连接,并请求发送消息;最后, Server
接收、解析请求的数据,并产生响应结果返回给 Client
。
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 <command> -h
帮助选项获取更详细的用法。
4、服务通信实操 – 在乌龟模拟器的指定位置孵化一个小乌龟
通过ROS内置的乌龟模拟器(turtlesim
)来进行服务通信的实操,在乌龟模拟器的指定位置孵化一个小乌龟。
实现的步骤如下:
步骤1:在新终端中启动roscore
roscore
步骤2:在新终端中启动乌龟模拟器节点turtlesim_node
rosrun turtlesim turtlesim_node
步骤3:通过调试工具rqt_service_caller
和编程的方式在乌龟模拟器的指定位置孵化一个小乌龟。
4.1 调试工具实现
通过rqt_service_caller
工具模拟服务请求:
- 启动
rqt_service_caller
工具
rosrun rqt_service_caller rqt_service_caller
- 通过图形化配置参数,如果所示,选择孵化服务
/spawn
,在Request
中配置孵化位置、角度、乌龟名字请求参数,然后点击右上角call 发送请求,如果乌龟模拟器响应成功,会在Response
中显示结果,并在乌龟模拟器turtlesim
中孵化出一个小乌龟。
4.2 编程实现(C++)
在beginner_tutorials
软件包的src
目录下创建服务客户端源文件:
roscd beginner_tutorials
cd src
touch turtle_spawn_client.cpp
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;
}
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)
4.2.3 编译、运行
在你的工作空间下执行catkin_make编译,将turtle_spawn_client.cpp
编译成可执行文件turtle_spawn_client
。编译后,在终端中执行过程如下所示。
4.3 编程实现(Python)
在beginner_tutorials
软件包的scripts
目录下创建服务客户端源文件:
roscd beginner_tutorials
cd scripts
touch turtle_client.py
chmod +x turtle_client.py
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()
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}
)
4.2.3 编译、运行
其实这个例子很简单,不需要编译,直接执行python文件就行。但是我们还是养成习惯吧,每次创建和修改代码后,就catkin_make编译一下,即使是Python节点也必须使用它。这是为了确保能为创建的消息和服务自动生成Python代码。
5、服务命令实操
ROS提供了一些命令行工具帮助我们查看Service的信息。通过小乌龟模拟器(turtlesim)来实操服务命令。
5.1 rosservice list
rosservice list
输出活跃(当前正在运行)服务的信息。
list命令显示有两个与rosout节点有关的服务:/rosout/get_loggers和/rosout/set_logger_level。其余的都是turtlesim节点提供了9个服务。
5.2 rosservice argc
rosservice argc[service]
输出服务的所有参数。
5.3 rosservice type
rosservice type [service]
输出服务的类型。
5.4 rosservice find
rosservice call [service]
按服务的类型查找服务。
5.5 rosservice uri
rosservice uri
输出服务的ROSRPC uri。
5.6 rosservice info
rosservice info [service]
输出服务的信息。
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"
ROS.otg. ROS教程[EB/OL]. 2020-12-22[2022-7-5].
http://wiki.ros.org/cn/ROS/Tutorials. ↩︎ROS.otg. rosservice[EB/OL]. 2020-12-22[2022-7-5].
https://wiki.ros.org/rosservice. ↩︎