roscpp介绍(二)
Service
service是请求-反馈通信机制,消息的传输是双向的,有反馈的,service的传输与topic不同,不是以固定的频率传输,不连续,而是在需要的时候向服务器发起请求。请求的一方为客户端(Client),提供服务的一方为服务器端(Server)。
1. 创建Service服务
创建test/Greeting.srv文件
string name //短横线上边部分是服务请求的数据
int32 age
---
string feedback //短横线下面是服务回传的内容
2. 修改CMakeLists.txt文件
...
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
message_genaration
)
...
add_service_files(
FILES
Greeting.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
...
3. 编译生成自定义类型
CMakeLists.txt 修改完成后进行catkin_make
,系统就会生成在代码中可用的Greeting类型。在代码中使用,只需要#include <test/Greeting.h>
,然后即可创建该类型的srv。
test::Greeting grt;
grt.request.name = "han";
grt.request.age = 20;
也可将service类型的数据看成结构体(嵌套了两个结构体,分别是请求和响应)
struct Greeting
{
struct Request
{
string name;
int age;
}request;
struct Response
{
string feedback;
}response;
}
4. 创建服务节点
文件位置:test/src/server.cpp
#include<ros/ros.h>
#include<test/Greet>
bool handle_function(test::Greeting::Request &req,test::Greeting::Response &res)
{
ROS_INFO("request from %s with age %d",req->name.c_str(),req->age);//显示请求信息
res.feedback = "Hi"+req.name+", I am server"; //处理请求,结果写入response
return true; //返回true,正确处理了请求
}
int main(int argc,char **argv)
{
ros::init(argc,argv,"server");//解析参数,命名节点
ros::NodeHandle nh; //创建句柄,实例化node
ros::ServiceServer ser = nh.adverticeService("service_greeting",handle_function);//写明服务的处理函数
ros::spin();
return 0;
}
服务的处理操作在handle_function()中,它的输入参数是Greeting的Request和Response两部分(不是整个Greeting对象),通常在此处理函数中,对Request数据进行操作,结果写入Response中。
在roscpp中,处理函数的返回值是bool型,就是服务是否成功执行(不是输入Request,输出Response)。
5. 创建服务请求节点
文件位置:test/src/client.cpp
#include<ros/ros.h>
#include<test/Greeting>
int main(int argc,char** argv)
{
ros::init(argc,argv,"client");// 初始化,节点命名为"client"
ros::NodeHandle nh;
ros::ServiceClient client = nh.ServiceClient<test::Greeting>("service_greeting"); // 定义service客户端,service名字为“service_greeting”,service类型为test
test::Greeting srv; // 实例化srv,设置其request消息的内容,这里request包含两个变量,name和age,见Greeting.srv
srv.name = "han";
srv.age = 20;
if (client.call(srv))//调用时可以直接用client.call(srv),返回的结果为是否成功调用远程服务(不是Response)
{
ROS_INFO("Response from server: %s",srv.response.feedback.c_str()); // 我们的response部分中的内容只包含一个变量response,要将其转变成字符串
}
else
{
ROS_ERROR("Failed to call service test");
return 1;
}
return 0;
}
6. 继续修改CMakeLists.txt
add_executable(server,server.cpp)
add_dependencies(server,test_generate_message_cpp)
target_link__libraries(server
${catkin_LIBRARIES}
)
add_executable(client,server.cpp)
add_dependencies(client,test_generate_message_cpp)
target_link__libraries(client
${catkin_LIBRARIES}
)
7. 修改package.xml
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
8. 执行
cd ~/catkin_ws
catkin_make
roscore
rosrun test server
rosrun test client