想要使用ROS编写一个自己的service,无奈网上都是beginner_tutorial 的各种改版,里面的AddTwoInts.srv 文件怎么写没有人说,多少人是在道听途说呢?于是乎,自己写一个.
料想需要这篇文章的朋友已经有一定的ROS基础,熟悉创建包,了解主要的文件关系,因此一些细节不再详述.下面正式开始.
一. 服务的格式定义与编译
1.1 编写 .srv 文件
创建了一个包 test_pkg,用于存放各种测试文件.默认地,该包中会包括 CMakeLists.txt
,package.xml
两个文件和 src
文件夹.再在该包中创建一个文件夹 srv
在 srv
文件中新建 .srv
文件,此处以两个数相乘为例,故取名为 multiply.srv
,文件内容如下
float64 a
float64 b
---
float64 c
其中,三条短线上方的代表请求参数,下方的代表相应参数.这是ROS规定的格式.注意不能用float
,个人测试没编译通过.
1.2 编译
修改 CMakeLists.txt
文件
- 在
find_package()
中包含message_generation
- 取消注释或添加
add_service_files(FILES multiply.srv)
- 取消注释或添加
generate_messages(DEPENDENCIES std_msgs)
修改 package.xml
文件
- 取消注释或添加
<build_depend>message_generation</build_depend>
- 取消注释或添加
<exec_depend>message_runtime</exec_depend>
在ROS空间下执行
catkin_make
如果编译没有报错,说明一切正常.此时可以稍微检查一下效果.
1.3 编译测试
输入指令
rossrv show test_pkg/multiply
将输出
float64 a
float64 b
---
float64 c
查找文件 multiply.h
find -name multiply.h
将输出路径
./devel/include/test_pkg/multiply.h
我们并没有手动写过这个头文件,这是系统根据multiply.srv
自动生成的,这个文件一会儿将使用!
二. 编写服务端与客户端
2.1 源文件
2.1.1 服务端源文件
在 src
文件夹下创建服务端源文件,此处命名为 server.cpp
,其内容如下
#include "ros/ros.h"
#include "test_pkg/multiply.h"
/*
* 乘法计算回调函数
* @param req, 请求参数
* @param res, 响应参数
*/
bool multiplyCallback(test_pkg::multiply::Request &req, test_pkg::multiply::Response &res)
{
res.c = req.a * req.b;
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "server");
ros::NodeHandle nh;
// 创建一个服务 multiply_service,当被调用时触发回调函数 multiplyCallback
ros::ServiceServer server = nh.advertiseService("multiply_service", multiplyCallback);
ros::spin();
return 0;
}
其使用了之前系统生成的multiply.h
文件夹.在回调函数中,完成乘法运算.
2.1.2 客户端源文件
在 src
文件夹下创建客户端源文件,此处命名为 client.cpp
,其内容如下
#include "ros/ros.h"
#include "test_pkg/multiply.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "client");
ros::NodeHandle nh;
// 客户端也调用服务 multiply_service
ros::ServiceClient client = nh.serviceClient<test_pkg::multiply>("multiply_service");
// 参数赋值,调用服务测试
test_pkg::multiply srv;
srv.request.a = 6.0;
srv.request.b = 6.0;
if (client.call(srv))
{
ROS_INFO("Success! %f * %f = %f", srv.request.a, srv.request.b, srv.response.c);
}
else
{
ROS_INFO("Failed to call service multiply_service");
return 1;
}
return 0;
}
客户端通过 .call
函数调用服务端,调用成功或失败后都有对应的输出.
2.2 编译文件
2.2.1 修改 CMakeLists.txt
文件
- 添加或取消注释,使得有
add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server test_pkg_gencpp)
add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client test_pkg_gencpp)
include_directories(include ${catkin_INCLUDE_DIRS})
2.2.2 编译
执行指令
catkin_make -DCATKIN_WHITELIST_PACKAGES=test_pkg # 编译指定的包
source ./devel/setup.bash # 使生效
2.3 测试
在三个终端分别输入
roscore
rosrun test_pkg server
rosrun test_pkg client
结果如下
除了以上常规的测试之外,还可以直接在终端调用服务. 在roscore
和 server
运行的时候,使用rosservice list
查看当前服务, 使用 call
调用服务
rosservice call /multiply_service 3 3
计算结果为
9
9
9,前面的 c 是之前 .srv
文件里定义的变量名.
完整package下载链接: https://pan.baidu.com/s/1r7d0pVBPRdV4sqtYFcSPng 提取码: 46gt
— 完 —