这一节主要是学习如何自定义一个服务类型并使用它。
服务数据是以.srv结尾的文件,是一个用于描述ROS服务信息简单文本文件,用于生成不同语言消息的源代码。srv文件存放在package文件夹下srv
文件夹中。
经过下面四个步骤,返回到workspace目录进行catkin_make
,ROS就能根据你的srv文件产生C++需要的源文件定义。
srv文件每一行用段类型和段名组成,段类型有:
此外,因为服务信息内容由三横线分为上下两部分,分别是请求(request)和回应(response)。如:
int64 A
int64 B
---
int64 Sum
上面A B是请求数据,下面Sum是回应数据,数据类型都是int64。
确保package内package.xml文件以下内容已经被解注释:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
这是为了保证msg文件能够转换成C+,Python和其他语言的源文件代码,第一行是编译的时候的依赖,第二行是执行时依赖。
确保find_package命令存在message_generation
模块。
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
确保generate_messages语句已经加入依赖(要在catkin_package前):
generate_messages(
DEPENDENCIES
std_msgs
)
确保catkin_package语句已经有了运行时依赖message_runtime
catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...)
确保add_service_file语句已经增加了想要的srv文件:
add_service_files(
FILES
Service1.srv
Service2.srv
)
CMakeLists.txt一共要进行四处确认find_package
generate_messages
catkin_package
和add_service_files
在这个例子中,客户端将两个int64数据发送到服务器,服务器对这两个数据求和后返回他们的总和。
在package目录创建一个srv文件夹,并创建自己的自定义消息:
mkdir srv
cd srv
touch TwoIntsSum.srv
消息格式如下(TwoIntsSum.srv):
int64 a
int64 b
---
int64 sum
package.xml添加固定的片段:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
一个用于编译时信息产生依赖
;
另一个用于执行时信息依赖
在find_package
中增加message_generation
:
在generate_messages语句已经加入依赖:(不可以缺少!)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package
命令增加message_runtime
:
message_runtime
对于msg
和srv
都有效果,虽然名字叫做message_*
add_service_files
命令增加TwoIntsSum.srv
:
回到工作空间根目录,使用catkin_make
进行编译,如果出现以下打印,说明一切正常:
此时,ros已经根据你的配置生成了C++编程所需要的头文件了和msg一样放在workspace/devel/include/package/里面:
service_test/ ├── TwoIntsSum.h ├── TwoIntsSumRequest.h └── TwoIntsSumResponse.h 0 directories, 3 files
客户端代码程序代码:
#include
#include "service_test/TwoIntsSum.h"
int main(int argc,char**argv)
{
ros::init(argc,argv,"twoNumberClient");
ros::NodeHandle n;
ros::service::waitForService("/sumupTwo");
ros::ServiceClient client=n.serviceClient<service_test::TwoIntsSum>("/sumupTwo");
service_test::TwoIntsSum srv;
srv.request.a=1;
srv.request.b=2;
ROS_INFO("Call service to add numbers up request [a:%d,b:%d]",srv.request.a,srv.request.b);
client.call(srv);
ROS_INFO("Get result from server ,the sum is : %d",srv.response.sum);
return 0;
}
服务器程序代码:
#include
#include "service_test/TwoIntsSum.h"
bool Callback(service_test::TwoIntsSum::Request &req,service_test::TwoIntsSum::Response &res)
{
ROS_INFO("Receieve two number from client a=[%d],b=[%d]",req.a,req.b);
res.sum=req.a+req.b;
return true;
}
int main(int argc,char ** argv)
{
ros::init(argc,argv,"Sumserver");
ros::NodeHandle n;
ros::ServiceServer server=n.advertiseService("/sumupTwo",Callback);
ROS_INFO("Server ready");
ros::spin();
return 0;
}
OK,最后一步,往这个包对应的CMakeLists.txt中添加:
add_executable(clientGiveTwonum src/clientTwonumber.cpp)
target_link_libraries(clientGiveTwonum ${catkin_LIBRARIES})
add_dependencies(clientGiveTwonum ${PROJECT_NAME}_gencpp)
add_executable(serverCal src/serverSumup.cpp)
target_link_libraries(serverCal ${catkin_LIBRARIES})
add_dependencies(serverCal ${PROJECT_NAME}_gencpp)
注意相比于msg这里多了一个add_dependencies。
回到workspace目录,catkin_make!看到如下情况说明一切顺利:
你使用sensor.msg,最后会产生一个sensor.h。代码中表现是
package::sensor
。
开启第一个终端,用来启动roscore核心:
roscore
这个指令再复习一下:
Usage: rosrun [--prefix cmd] [--debug] PACKAGE EXECUTABLE [ARGS] rosrun will locate PACKAGE and try to find an executable named EXECUTABLE in the PACKAGE tree. If it finds it, it will run it with ARGS.
第二个终端,启动service_test中的应用serverCal
rosrun service_test serverCal
第三个终端,启动service_test中的应用clientGiveTwonum
rosrun service_test clientGiveTwonum
结果如下:
(客户端)
junwu@Room:~/Desktop/myWS$ rosrun service_test clientGiveTwonum [ INFO] [1648649460.485700436]: Call service to add numbers up request [a:1,b:2] [ INFO] [1648649460.486496542]: Get result from server ,the sum is : 3
(服务端)
junwu@Room:~/Desktop/myWS$ rosrun service_test serverCal [ INFO] [1648649458.228923550]: Server ready [ INFO] [1648649460.486441702]: Receieve two number from client a=[1],b=[2]
[1] https://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv#Common_step_for_msg_and_srv