ROS service入门到应用

本文介绍 ROS 中 Service 的基本概念及应用场景,对比 Topic 模型,详细讲解如何自定义 Service 类型并实现客户端和服务端交互。

ROS Service 入门到应用

使用ros有一段时间了,但是一般topic类型的通信方式使用的最多,很少使用service,所以对service也就是简单的了解,并没有真正的使用过,最近要用到service通信模式,所以自己就要去学,但是看了官网的教程之后,还不是特别明确到底怎么去做。官网教程链接:http://wiki.ros.org/ROS/Tutorials/WritingServiceClient%28c%2B%2B%29
在这里,对于没用过service或者刚开始学习ros的朋友来说,一般都有如下疑问?
(1)service与topic有什么区别,一般什么时候需要用到service?
个人理解:topic与service最大的区别在于topic发送数据时,对方是否成功接收是没有反馈的,而service是有一个对方的反馈的,而且返回值不一定是bool类型,也可以是int,string等类型。所以当你需要接收方有反馈给你时,这时需要用到service。而且据官网讲(http://wiki.ros.org/ROS/Technical%20Overview)service的通信开销是很大的,所以对于频率比较高的通信最好用topic。
另外,在这里也提出自己的一点疑惑,topic跟service分别是TCP/IP通信中UDP与TCP通信协议的封装吗?我本来一位topic就是UDP的封装,而service就是TCP的封装,但是也不确定,ros官网上也没找到明显的解释,所以懂的麻“烦指教下。
(2)service像topic一样有很多自带的标准类型吗?
个人理解:topic使用的msg有很多自带的类型,如std_msgs、sensor_msgs、geometry_msgs等,所以我在使用service时也在想,service是不是也有很多这种标准类型,遗憾的是我找到很少,就找到了std_srvs中的几个类型,所以你想要用service的话,需要自己定义service类型。(如果有知道很多service标准类型的话,请指教下,我找了好几遍没找到)

下面我们开始使用service吧

(1) 首先打开你的工作空间至src目录下,例如我的工作空间为catkin_ws,那么:

这里写代码片
cd ~/catkin_ws/src

(2)在你的工作空间下创建我们我们service用的package:

 catkin_creat_pkg learn_srvs roscpp rospy std_srvs std_msgs message_generation

(3) 接下来我们自己定义一个service, 名字为learn.srv

打开包所在的目录

 cd catkin_ws/src/learn_srvs

新建srv文件夹

mkdir srv 

创建learn.srv文件

cd srv/
 gedit learn.srv

假设客户端发送的request为两个浮点型的数,x,y。服务端返回的response为bool类型的received, 当然变量的名字x,y,received是由我们自己定义的,
learn.srv内容如下:

float64 x
float64 y
---
bool received

保存,这样我们就创建了一个自己的service文件,
下面修改CMakeLists.txt使新生成的srv生效,CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 2.8.3)
project(learn_srvs)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_srvs
  std_msgs
  message_generation
)

 add_service_files(
   FILES
   learn.srv
 )

 generate_messages(
   DEPENDENCIES
   std_msgs
 )


catkin_package(
  INCLUDE_DIRS include
)

include_directories(
  ${catkin_INCLUDE_DIRS}
)

保存,去工作空间下catkin_make编译,即可生成与service相应的头文件
进到devel文件夹下会看到新生成的include目录,这里面便有我们新建的srv的头文件,现在就可以开始按照官网的教程写客户端与服务端了

 cd ~/catkin_ws/devel/include/learn_srvs/

我在learn_srvs/src下边写了两个node测试,如下:
客户端:learn_srv_client.cpp

 #include "ros/ros.h"
#include "learn_srvs/learn.h"
#include <cstdlib>

int main(int argc, char **argv)
{
  ros::init(argc, argv, "learn_srv_client");
  if (argc != 3)
  {
    ROS_INFO("need x,y");
    return 1;
  }

  ros::NodeHandle n;
  ros::ServiceClient client = n.serviceClient<learn_srvs::learn>("learn_srvs");
  learn_srvs::learn srv;
  srv.request.x = atoll(argv[1]);
  srv.request.y = atoll(argv[2]);
  if (client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.received);
  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }

  return 0;
}

服务端:learn_srv_server.cpp

 #include "ros/ros.h"
#include "learn_srvs/learn.h"

bool add(learn_srvs::learn::Request  &req,
         learn_srvs::learn::Response &res)
{
  res.received = 1;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.x, (long int)req.y);
  ROS_INFO("sending back response: [%ld]", (long int)res.received);
  return true;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "learn_srv_server");
  ros::NodeHandle n;

  ros::ServiceServer service = n.advertiseService("learn_srvs", add);
  ROS_INFO("Ready to learn srvs.");
  ros::spin();

  return 0;
}

当然CMakeLists.txt也相应修改如下:

 cmake_minimum_required(VERSION 2.8.3)
project(learn_srvs)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_srvs
  std_msgs
  message_generation
)

 add_service_files(
   FILES
   learn.srv
 )

 generate_messages(
   DEPENDENCIES
   std_msgs
 )


catkin_package(
  INCLUDE_DIRS include
)

include_directories(
  ${catkin_INCLUDE_DIRS}
)
add_executable(learn_srv_client_node src/learn_srv_client.cpp)
add_executable(learn_srv_server_node src/learn_srv_server.cpp)

target_link_libraries(learn_srv_client_node 
   ${catkin_LIBRARIES}
 )
target_link_libraries(learn_srv_server_node
   ${catkin_LIBRARIES}
 )

catkin_make 编译工作空间,然后,在终端运行即可看到结果:

 rosrun learn_srvs learn_srv_server_node
 rosrun learn_srvs learn_srv_client_node 1 2

需要注意的是:
(1)这个例子要先启动服务端再启动客户端才行
(2)在实际应用中发送端为客户端,相当于topic里面的发布者。接收端为服务端,相当于topic里面的订阅者。

其实没啥难的,多写就好了,有问题欢迎交流讨论。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值