ROS学习笔记(四)——服务端与客户端

ROS服务与话题相似,但服务与话题不同之处在于:服务在消息发送者发送消息后,接受者接受消息后要做出相应的回应。
使用服务时,要先创建服务,相对于消息使用在package/msg目录下创建,服务则在package/srv目录下创建(但服务端和客户端定义的cpp文件还同样是在/src目录下)。
创建服务的步骤
1、在包目录下创建srv文件夹
2、在srv文件夹下创建.srv文件,例如AddTwoInts.srv,文件内容如下:

int32 a
int32 b
---         //“---”上方表示 request数据类型
int32 sum   //下面是 response类型

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

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

3、配置CMakeLists.txt
配置方式与自定义消息格式配置相似,除了下面这一步,其余都一样(参照上一篇博客):
将 AddTwoInts.srv加入 add_service_files(),表示要编译的服务类型文件。
4、验证服务类型是否创建成功

rossrv show package_name/AddTwoInts  //package_name为包名
若显示:
int32 a
int32 b
---
int32 sum
则创建成功

5、编译,生成头文件

catkin_make

devel/include/package_name/AddTwoInts.h

devel/include/package_name/AddTwoIntsRequest.h

devel/include/package_name/AddTwoIntsResponse.h

创建客户端和服务端来使用服务
1、创建server节点
在/src/listener目录下创建listener_srv.cpp文件(注:节点包可以随意,可以一个节点一个文件夹,也可以多个节点共用文件夹,只是注意在后面修改CMakeLists.txt文件时注意路径)

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

//回调函数定义,参数类型需要与所服务类型保持一致
bool add(package_name::AddTwoInts::Request  &req,
         package_name::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;     //正常运行时,不会执行到。
}

2、创建client节点
talkersrv.cpp

#include "ros/ros.h"    //ros.h 包含ros程序常用的头文件。
#include "package_name/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<package_name::AddTwoInts>("add_two_ints");
  ros::Rate loop_rate(1);  //设置发布请求频率
  int count = 0;    //发布请求计数
  package_name::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;
}

3、修改CMakeLists.txt

add_executable(listener_srv src/listener/listener_srv.cpp)
target_link_libraries(listener_srv ${catkin_LIBRARIES})
add_dependencies(listener_srv ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

add_executable(talker_srv src/talker/talker_srv.cpp)
target_link_libraries(talker_srv ${catkin_LIBRARIES})
add_dependencies(talker_srv ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

4、编译运行

catkin_make
roscore
rosrun package_name listenersrv
rosrun package_name talker_srv

参考文章

你可能感兴趣的:(ros,自动驾驶)