使用方法 ros_ROS服务编程

本文详细介绍了如何在ROS中创建、配置和使用自定义服务类型,包括创建服务类型、配置package.xml和CMakeLists.txt、验证服务类型、编译服务类型以及创建服务的client和server节点。ROS服务由client发送请求,server响应,是项目开发中常见的通信方式。
摘要由CSDN通过智能技术生成
上篇我们以小乌龟为实例,介绍ROS服务基本概念和相关指令用法,本篇介绍如何自定义服务类型以及实现服务。

一. 创建服务类型

roscd beginner_tutorials/
mkdir srv
cd srv
touch AddTwoInts.srv

将以下内容复制进去:

int32 a
int32 b
---
int32 sum

“---”上方表示 request数据类型,两个加数,下面是 response类型,表示加数之和。

至此我们创建了一个自定义服务类型。

文件链接:

ahuer2435/ros_program​github.com
15682f8b532e0370f0ec4c44034e9096.png

和消息类型一样,服务类型最终也是要编译为.h头文件,才能被程序使用,所以以下步骤与

ROS 消息​mp.weixin.qq.com
d33d9dd8a4998958b9c035d38c57201a.png

篇中消息配置非常相似。

二. 配置package.xml

在 package.xml文件中添加如下三行,使用任何自定义消息,都必须使用这三行。

<build_depend>message_generation</build_depend>
<build_export_depend>message_runtime</build_export_depend>
<exec_depend>message_runtime</exec_depend>

文件链接:

https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/package.xml​github.com

这一步在

ROS 消息​mp.weixin.qq.com
d33d9dd8a4998958b9c035d38c57201a.png

篇已经做过,这里不必再做,但是如果是在其他包中,新建服务类型,必须要做这一步。

三. 配置CMakeLists.txt

将 message_generation加入到 find_package(), find_package()要与 package.xml文件中的 build_depend一致,表示编译时依赖的包。

将 AddTwoInts.srv加入 add_service_files(),表示要编译的服务类型文件。

放开 generate_messages(),表示生成消息头文件。

将 message_runtime加入 catkin_package()表示导出运行时依赖。

文件链接:

https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/CMakeLists.txt​github.com

除了第2步以外,其他与

ROS 消息​mp.weixin.qq.com
d33d9dd8a4998958b9c035d38c57201a.png

篇保持一致,第二步添加要编译的服务类型文件。至此我们完成服务类型配置。

四. 验证服务类型

rossrv show beginner_tutorials/AddTwoInts

输出如下:

int32 a
int32 b
int32 sum

表明服务类型创建成功。

五. 编译服务类型

catkinmake

编译完之后,会生成三个头文件,如下:

devel/include/beginnertutorials/AddTwoInts.h

devel/include/beginnertutorials/AddTwoIntsRequest.h

devel/include/beginnertutorials/AddTwoIntsResponse.h

六. 使用服务类型

和话题类似,ROS服务也有两部分构成:client和 server, client发送请求, server提供服务,响应请求。

1. 创建server节点

cp listenermsg.cpp listenersrv.cpp

做如下修改:第2行,引入服务类型头文件。第16行,修改节点名。第20行,定义一个服务端,使用 ServiceServer类,定义服务者 service,通过句柄 NodeHandle的 advertiseService方法初始化,此方法需要指令所提供的服务名字和服务回调函数,前者相当于订阅者的话题名,后者相当于订阅者的回调函数。第5行到第11行,定义回调函数,注意其参数类型需要为服务类型,有两项,前者是请求类型,对应第5步中的 AddTwoIntsRequest.h头文件,后者是服务类型,对应 AddTwoIntsResponse.h,

至于头文件内容不需要关心,直接引用其中数据即可。修改后源码如下:

#include "ros/ros.h"  //ros.h 包含ros程序常用的头文件。
#include "beginner_tutorials/AddTwoInts.h"  //引用服务类型头文件

//回调函数定义,参数类型需要与所服务类型保持一致
bool add(beginner_tutorials::AddTwoInts::Request  &req,
         beginner_tutorials::AddTwoInts::Response &res)
{
  res.sum = req.a + req.b;      //更新响应值。
  ROS_INFO("request: x=%d, y=%d", req.a, req.b);
  ROS_INFO("sending back response: [%d]", res.sum);
  return true;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener_srv");  //初始化ros,并命令节点名。
  ros::NodeHandle n;        //初始化节点,调用ros api接口句柄。

  //定义一个服务者,服务名字:add_two_ints,服务回调函数:add
  ros::ServiceServer service = n.advertiseService("add_two_ints", add);
  ros::spin();  //不返回函数,监听服务节点中的回调队列,并执行回调函数。
  return 0;     //正常运行时,不会执行到。
}

可参考链接:

https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/src/listener/listener_srv.cpp​github.com

2. 创建client节点

cp talkermsg.cpp talkersrv.cpp

做如下修改:第2行,引入服务类型头文件。第6行,修改节点名。第9行,定义一个客户端,使用 ServiceClient类定义客户端 client,通过句柄 NodeHandle的 serviceClient()函数初始化。serviceClient()是一个模板函数,模板参数为服务类型,函数参数为服务名,这两个都需要与服务端保持一致。第12行,定义一个服务类型变量。第14和15行,更新变量。第16行,发送请求,并判断请求响应结果,如果正常影响,则打印响应值,否则报错。修改之后源码如下:

#include "ros/ros.h"    //ros.h 包含ros程序常用的头文件。
#include "beginner_tutorials/AddTwoInts.h"  //引用服务类型头文件

int main(int argc, char **argv)
{
  ros::init(argc, argv, "talker_srv");  //初始化ros,并命令节点名。
  ros::NodeHandle n;    //初始化节点,调用ros api接口句柄。
  //定义一个客户端
  ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
  ros::Rate loop_rate(1);  //设置发布频率
  int count = 0;    //发布请求计数
  beginner_tutorials::AddTwoInts srv;   //定义服务变量
  while (ros::ok()){    //检测节点是否正常运行
    srv.request.a = count;      //更新服务变量值。
    srv.request.b = count+1;
    if (client.call(srv)) {     //发送请求
      ROS_INFO("Sum: %d", srv.response.sum);  //收到请求响应。
    }
    else {
      ROS_ERROR("Failed to call service add_two_ints"); //请求响应失败
      return 1;
    }
    ros::spinOnce();    //处理回调函数,会返回,这里也可以不加,因为此节点没有回调函数。
    loop_rate.sleep();  //与Line 10配套使用,用于控制发布频率。
    ++count;            //消息计数。
  }
  return 0;
}

可参考链接:

https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/src/talker/talker_msg.cpp​github.com

3. 添加到CMakeLists.txt

addexecutable(listenersrv src/listener/listenersrv.cpp)
targetlinklibraries(listenersrv ${catkinLIBRARIES})
adddependencies(listenersrv ${${PROJECTNAME}EXPORTEDTARGETS} ${catkinEXPORTEDTARGETS})
addexecutable(talkersrv src/talker/talkersrv.cpp)
targetlinklibraries(talkersrv ${catkinLIBRARIES})
adddependencies(talkersrv ${${PROJECTNAME}EXPORTEDTARGETS} ${catkinEXPORTEDTARGETS})

添加编译新创建的两个节点项。

文件链接:

https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/CMakeLists.txt​github.com

4. 编译运行

catkin_make
roscore
rosrun beginnertutorials listenersrv
rosrun beginnertutoria talker_srv

运行结果如下:

12b4a679e856879a26cbb1199257a6fb.png

七. 小结

ROS服务与话题比较类似,可以对应ROS 消息篇对比学习,其中步骤也比较相似。ROS服务与话题的主要区别是,消息发送者发送数据后,需要对方做出回应,在实际项目开发过程中,这两者都是比较常用的通信方式。下一篇介绍ROS Parameter。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值