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
参考文章