第一节:ROS的服务
摘要:
介绍ROS的服是双向的通信,客户端提交,服务端处理后返回到客户端。
1. *理论介绍*
自定义数据类型,根据自定义数据类型进行处理,客户端请求,服务端处理之后,返回客户端,是一种双向的通信机制。
2. *功能实现*
创建一个客户端,输入求积的两个数
创建一个服务端,处理求积的回调函数,并返回在输出端显示结果
3. *步骤实现*
3.1在ROS的工作空间中,创建一个功能包,并且进行编译:
wpf@wpfpc:$ cd ~/catkin_fs/src
wpf@wpfpc:~/catkin_fs/src$ catkin_create_pkg test_addtwo std_msgs roscpp rospy
wpf@wpfpc:~/catkin_fs/src$ cd ..
wpf@~/catkin_fs$ catkin_make
文件功能包的文件目录如下
wpf@wpf:~/catkin_ps/src/test_addtwo$ tree
.
├── CMakeLists.txt
├── include
│ └── test_addtwo
├── package.xml
├── src
│ ├── client1.cpp
│ └── server1.cpp
└── srv
└── AddTwoInts.srv
4 directories, 5 files
3.2 修改package.xml的内容
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>message_generation</build_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>message_runtime</exec_depend>
创建src 文件夹和 AddTwoInts.srv文件,
int64 a
int64 b
---
int64 sum
关键是加上两句话
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
进行catkin_make 操作,
/home/wpf/catkin_ps/devel/include/test_srv
路径下生成三个文件
wpf@wpf:~/catkin_ps/devel/include/test_srv$ ls
PassWord.h PassWordRequest.h PassWordResponse.h
在创建的功能包的src目录下创建两个文件
├── client1.cpp
└── server1.cpp
3.3 修改功能包中CMakeList.txt的内容
3.4 代码修改之后,编译成功之后即可运行
3.5 打开四个终端分别执行,一个roscore;两个节点,以及运行rqt查看节点之间的通信关系。
wpf@wpfpc:~/catkin_fs$ roscore
wpf@wpfpc:~/catkin_fs$ wpf@wpf:~$ rosrun test_addtwo server1
wpf@wpfpc:~/catkin_fs$wpf@wpf:~$ rosrun test_addtwo client1 3 4
wpf@wpfpc:~/catkin_fs$ rosrun rqt_graph rqt_graph
代码运行结果如下:
客户端
wpf@wpf:~$ rosrun test_addtwo client1 3 4
[ INFO] [1654681331.194028686]: sum: 7
服务端
wpf@wpf:~$ rosrun test_addtwo server1
[ INFO] [1654681326.655080262]: Ready to add two ints.
[ INFO] [1654681331.193792048]: request: x=3, y=4
[ INFO] [1654681331.193824662]: sending back response: [7]
节点之间的通信框图如下:
*实验分析:*
本实验,实现了节点之间的通信功能,由图可知,无需多言。
代码附录
服务端代码
#include "ros/ros.h"
#include "test_addtwo/AddTwoInts.h"
// service回调函数,输入参数req,输出参数res
bool add(test_addtwo::AddTwoInts::Request &req,
test_addtwo::AddTwoInts::Response &res)
{
// 将输入参数中的请求数据相加,结果放到应答变量中
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.sum);
return true;
}
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "add_two_ints_server");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个名为add_two_ints的server,注册回调函数add()
ros::ServiceServer service = n.advertiseService("add_two_ints", add);
// 循环等待回调函数
ROS_INFO("Ready to add two ints.");
ros::spin();
return 0;
}
客户端代码
#include <cstdlib>
#include "ros/ros.h"
#include "test_addtwo/AddTwoInts.h"
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "add_two_ints_client");
// 从终端命令行获取两个加数
if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client X Y");
return 1;
}
// 创建节点句柄
ros::NodeHandle n;
// 创建一个client,请求add_two_int service,service消息类型是learning_communication::AddTwoInts
ros::ServiceClient client = n.serviceClient<test_addtwo::AddTwoInts>("add_two_ints");
// 创建learning_communication::AddTwoInts类型的service消息
test_addtwo::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
// 发布service请求,等待加法运算的应答结果
if (client.call(srv))
{
ROS_INFO("sum: %ld", (long int)srv.response.sum);
}
else
{
ROS_ERROR("Failed to call service add_two_ints");
return 1;
}
return 0;
}
CMakeLists.txt代码
cmake_minimum_required(VERSION 3.0.2)
project(test_addtwo)
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
add_service_files(
FILES
AddTwoInts.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
CATKIN_DEPENDS
message_runtime
)
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
add_executable(server1 src/server1.cpp)
add_executable(client1 src/client1.cpp)
add_dependencies(server1 ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(client1 ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(server1 ${catkin_LIBRARIES})
target_link_libraries(client1 ${catkin_LIBRARIES})