上海硅步ROS连载系列40期 创建服务器节点和客户端节点
转载 2017-11-24 15:46 上海硅步 来源:上海硅步本节介绍使用C++编写ROS消息服务器节点和客户端节点的方法和步骤,以及如何构建和测试这两个节点。
1.编写服务器节点代码
使用kdevelop在ros_tutorials/src目录下创建一个名为add_two_ints_server的C++文件:
$ roscd ros_tutorials
$ cd src
$ kdevelopadd_two_ints_server.cpp
输入如下代码:
#include"ros/ros.h"
#include "ros_tutorials/AddTwoInts.h"
bool add(ros_tutorials::AddTwoInts::Request &req,
ros_tutorials::AddTwoInts::Response&res)
{
res.sum = req.a + req.b;1
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::init(argc, argv,"add_two_ints_server");
ros::NodeHandle n;
ros::ServiceServer service =n.advertiseService("add_two_ints", add);
ROS_INFO("Ready to add two ints.");
ros::spin();
return 0;
}
部分代码解释如下:
#include "ros_tutorials/AddTwoInts.h"
ros_tutorials/AddTwoInts.h是由编译系统自动根据先前创建的srv文件生成的对应该srv文件的头文件。
bool add(ros_tutorials::AddTwoInts::Request &req,
ros_tutorials::AddTwoInts::Response&res)
该函数提供两个int值求和的服务,int值从Request里面获取,而返回数据装入Response内,这些数据类型都定义在srv文件内部,函数返回一个bool值。
{
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;
}
进行两个整数相加运算,结果存储在Response中。把Request和Response的一些信息记录日志,最后当运算完成时服务返回True。
ros::ServiceServerservice = n.advertiseService("add_two_ints", add);
创建服务service并在ROS网络上进行广播。
2.编写客户端节点代码
使用kdevelop在ros_tutorials/src目录下创建一个名为add_two_ints_client的C++文件:
$ roscd ros_tutorials
$ cd src
$ kdevelopadd_two_ints_client.cpp
输入如下代码:
#include"ros/ros.h"
#include "ros_tutorials/AddTwoInts.h"
#include
int main(int argc, char**argv)
{
ros::init(argc, argv,"add_two_ints_client");
if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client XY");
return 1;
}
ros::NodeHandle n;
ros::ServiceClient client =n.serviceClient ("add_two_ints");
ros_tutorials::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
if (client.call(srv))
{
ROS_INFO("Sum: %ld", (longint)srv.response.sum);
}
else
{
ROS_ERROR("Failed to call serviceadd_two_ints");
return 1;
}
return 0;
}
部分代码解释如下:
ros::ServiceClientclient = n.serviceClient ("add_two_ints");
为add_two_ints服务创建一个客户端。ros::ServiceClient对象用来随后调用服务。
ros_tutorials::AddTwoIntssrv;
srv.request.a= atoll(argv[1]);
srv.request.b= atoll(argv[2]);
实例化一个自动生成的服务类,并为其request成员赋值。一个服务类包含两个成员,request和response,也包括两个类的定义:Request和Response。
if(client.call(srv))
调用服务,调用完成后立即返回。如果服务调用成功,call()将返回true,此时srv.response中的值有效。如果服务调用失败,call()将返回false,srv.response中的值无效。
3.生成节点
打开~/catkin_ws/src/ros_tutorials/CMakeLists.txt,将以下代码添加到最后:
add_executable(add_two_ints_serversrc/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server${catkin_LIBRARIES})
add_dependencies(add_two_ints_serverros_tutorials_gencpp)
add_executable(add_two_ints_clientsrc/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client${catkin_LIBRARIES})
add_dependencies(add_two_ints_clientros_tutorials_gencpp)
这将会创建两个可执行程序,add_two_ints_server和add_two_ints_client。默认情况下,它们将会位于你的开发空间里面的ros_tutorials功能包目录下(~/catkin_ws/devel/lib/ros_tutorials),你可以直接调用它们或者使用rosrun运行它们。
运行 catkin_make:
# In your catkinworkspace
$ cd ~/catkin_ws
$ catkin_make
4.测试服务器和客户端节点
首先启动roscore:
$ roscore
在另一个终端窗口运行下面的命令启动服务器节点:
$ rosrun ros_tutorialsadd_two_ints_server
你会看到下面的输出:
Ready to add two ints.
新建一个终端,运行客户端节点:
$ rosrun ros_tutorials add_two_ints_client 2 3
你会看到类似下面的输出:
Requesting 2+3
2 + 3 = 5