本文最后更新于:2022年5月29日 上午
服务编程流程
- 创建服务器
- 创建客户端
- 添加编译选项
- 运行可执行程序
node1
发布一个话题,发布接收到数字总数
接收话题,话题接收一个int型
服务:求和,求话题接收到的所有数字的和
服务:清零
node2
发布一个话题,发布int,隔一个5S随机时间发布
隔60S后,调用求和服务,把结果打印出来。
接收话题,打印NOde1,接收到的数字数量。
1,创建程序包
在工作空间的src目录下:
1 2
| cd ~/catkin_ws/src/ catkin_create_pkg add_ints roscpp rospy std_msgs
|
2,修改package.xml作者邮箱
1 2
| cd ~/catkin_ws/src/ add_ints gedit package.xml
|
3,编译测试
在工作空间目录下:
4,定义新的消息
1 2 3
| cd ~/catkin_ws/src/add_ints mkdir msg echo "int64 num" > msg/Num.msg
|
5,修改package.xml
查看package.xml,确保它包含一下两条语句(接近末尾处),如果没有,添加进去:
1 2
| <build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend>
|
6,修改CMakeLists.txt文件
1)在find_packag函数的COMPONENTS的列表里增加message_generation,就像这样:
1 2 3 4 5 6
| find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation )
|
2)设置了运行依赖:
1 2 3 4 5
| catkin_package( ... CATKIN_DEPENDS message_runtime ... )
|
3)用你的.msg文件替代Message*.msg:
1 2 3 4
| add_message_files( FILES Num.msg )
|
4)取消generate_messages()的注释:
1 2 3 4
| add_message_files( FILES Num.msg )
|
7,检查ROS是否能够识消息
通过rosmsg show
命令检查:
1
| rosmsg show add_ints/Num
|
将会看到:
8,创建一个srv
1
| roscd add_ints mkdir srv
|
9,创建一个服务文件
1 2
| cd srv gedit AddInts.srv
|
输入一下内容:
1 2 3 4 5
| int64 a int64 b int64[13] --- int64 sum
|
10,增加额外的依赖项
修改CMakeLists.txt文件,删掉add_service_files的注释: 用你自己的srv文件名替换掉那些Service*.srv文件:
1 2 3 4
| add_service_files( FILES AddInts.srv )
|
11,检查ROS是否能够识该服务
通过rosmsg show
命令:
1
| rossrv show add_ints/AddInts
|
将会显示:
1 2 3 4 5
| int64 a int64 b int64[13] --- int64 sum
|
12,重新编译package
1 2 3
| cd ~/catkin_ws catkin_make
|
Service节点和Client节点程序
1,在add_ints/src目录下创建创建程序源代码
1)add_ints_server.cpp
实现一个服务器
- 初始化ROS节点;
- 创建Server实例;
- 循环等待服务请求,进入回调函数;
- 在回调函数中完成服务功能处理,并反馈应答数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include "ros/ros.h" #include "add_ints/AddInts.h" bool add(add_ints::AddInts::Request &req, add_ints::AddInts::Response &res) { if(req.b == 12) { res.sum = 0; for(int i=0;i<req.b;i++) res.sum += req.c[i]; ROS_INFO("sending back response: [%ld]", (long int)res.sum); } else { ROS_INFO("request: x=%ld", (long int)req.a); } return true; } int main(int argc, char **argv) { ros::init(argc, argv, "add_ints_server"); ros::NodeHandle n; ros::ServiceServer service = n.advertiseService("add_ints", add); ROS_INFO("Ready to add ints."); ros::spin(); return 0; }
|
2)add_ints_client.cpp
实现一个客户端
- 初始化ROS节点;
- 穿件一个Client实例;
- 发布服务请求数据;
- 等待Server处理之后的应答结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include "ros/ros.h" #include "add_ints/AddInts.h" #include <cstdlib> #include <ctime> int main(int argc, char **argv) { ros::init(argc, argv, "add_ints_client"); ros::NodeHandle n; ros::Rate loop_rate(0.2); ros::ServiceClient client = n.serviceClient<add_ints::AddInts>("add_ints"); add_ints::AddInts srv; srand(int(time(0))); srv.request.a = rand(); srv.request.b = 0; while(ros::ok()) { if (client.call(srv)) { if(srv.request.b == 12) ROS_INFO("Sum: %ld", (long int)srv.response.sum); srv.request.c[srv.request.b] = srv.request.a; srv.request.a = rand(); srv.request.b++; } else { ROS_ERROR("Failed to call service add_ints"); return 1; } if(srv.request.b == 13) srv.request.b = 0; else loop_rate.sleep(); } return 0; }
|
2,修改程序包的 CMakeLists.txt
添加可执行程序和可执行程序的链接库:
1 2 3 4 5 6
| add_executable(add_ints_server src/add_ints_server.cpp) target_link_libraries(add_ints_server ${catkin_LIBRARIES}) add_dependencies(add_ints_server add_ints_gencpp) add_executable(add_ints_client src/add_ints_client.cpp) target_link_libraries(add_ints_client ${catkin_LIBRARIES}) add_dependencies(add_ints_client add_ints_gencpp)
|
3,编译运行
1 2
| cd ~/catkin_ws catkin_make
|
编译完成后即可运行:
先启动master节点:
启动service节点:
1
| rosrun add_ints add_ints_server
|
启动客client节点:
1
| rosrun add_ints add_ints_client
|