ROS server与client的创建 catkin_make编译指定功能包
目录
一、自定义服务数据
1 创建.srv文件
建议将自定义数据单独编译到一个包内 不要放到某个程序包内,在编译过程中可执行文件是要依赖这个***.srv文件的,一旦重新编译,会因为srv对应.h文件没有生成而编译报错。
在工作空间中创建一个新的package
catkin_create_pkg srv_h message_generation roscpp std_msgs
这个包里面只存放自定义服务数据的.srv文件
在package内创建srv文件夹 和src处于同级
在srv文件夹内创建AddTwoInts.srv文件
内容如下
int64 a
int64 b
---
int64 sum
横线上是请求数据(request)
下面是应答数据(responce)
2.修改cmakelists.txt文件并编译
修改cmakelists的内容如下:
###在“srv”文件夹中生成服务
###1###############
add_service_files(
FILES
AddTwoInts.srv
)
###使用此处列出的任何依赖项生成添加的消息和服务
###2##########
generate_messages(
DEPENDENCIES
std_msgs
)
之后再catkin_make一下
同时我查看了之后生成的.h文件发现还有一点有趣的是:
生成了三个.h文件分别是:
srv.h ***Reque.h ***Responce.h
所以在定义回调函数的时候可以使用两种方法调用这个类的对象
bool Addcallback(srv_h::AddTwoInts::Request &req,
srv_h::AddTwoInts::Response &res)
或者:
bool Addcallback(srv_h::AddTwoIntsRequest &req,
srv_h::AddTwoIntsResponse &res)
二、创建server
1.创建service.cpp文件
还是创建一个新的包存放server节点
catkin_create_pkg ros_service roscpp std_msgs message_generation srv_h
依赖项加上之前的srv_h哪个自定义服务数据的包
在ros_service这个包里的src文件里面创建service.cpp文件
内容如下:
#include <ros/ros.h>
#include <srv_h/AddTwoInts.h>
#include <iostream>
using namespace std;
//回调函数
bool Addcallback(srv_h::AddTwoInts::Request &req,
srv_h::AddTwoInts::Response &res)
{
ROS_INFO("callback function");
res.sum = req.a +req.b;
ROS_INFO("request:x = %ld, y=%ld",(long int)req.a,(long int)req.b);//注意数据类型及转换
ROS_INFO("response:sum = %ld",(long int)res.sum);
return true;
}
int main(int argc, char **argv)
{
ros::init(argc,argv,"add_server");
ros::NodeHandle nh_;
ros::ServiceServer sevice = nh_.advertiseService("add_2ints",Addcallback);//(servicename,servicefunction)
ROS_INFO("start to add");
ros::spin();
return 0;
}
2.修改cmakelists.txt文件并编译
修改内容如下:
###1这句指定了可执行文件的名字为service
#######rosrun的时候和这个文件名字对应
add_executable(service src/service.cpp)
###2
add_dependencies(service service)
###3
target_link_libraries(service ${catkin_LIBRARIES})
如果之前创建pkg的时候依赖指定的没错不用修改package.xml
如果之前搞错了,则需要修改package.xml文件
然后catkin_make
3.测试service.cpp
打开roscore
打开service
rosrun ros_service service
再用手动输入函数进行输入
rosservice call add_2ints 5 6
call是rosservice的一个命令 add_2ints是service名,后面是两个参数
如果service端输出
[ INFO] [1623071252.956667181]: start to add
[ INFO] [1623071256.971379672]: callback function
[ INFO] [1623071256.971434949]: request:x = 5, y=6
[ INFO] [1623071256.971445098]: response:sum = 11
证明前面编写的没有问题
三、创建client
1.创建client.cpp文件
还是创建一个新的包存放client节点
catkin_create_pkg ros_client roscpp std_msgs message_generation srv_h
注意:创建新的包的原因是:放在一个包内,在运行的时候会报错——段错误(核心段已转储)个人怀疑和放在一个包内有关系
猜想:一个包运行两个node会出问题,在存储地址的调用上会重叠(请给位大神指正)
依赖项加上之前的srv_h那个自定义服务数据的包
在ros_client这个包里的src文件里面创建client.cpp文件
内容如下:
#include <cstdlib>
#include <ros/ros.h>
#include <srv_h/AddTwoInts.h>
using namespace std;
int main(int argc,char **argv)
{
ros::init(argc,argv,"add_client");
if(argc != 3)
{
ROS_INFO("add two ints input wrong");
return 1;
}
ros::NodeHandle nh_;
ros::ServiceClient client = nh_.serviceClient<srv_h::AddTwoInts>("add_2ints");
//(请求server名称)
srv_h::AddTwoInts srv;
srv.request.a = atoll(argv[1]); //输入的第一个参数
srv.request.b = atoll(argv[2]);//输入的第二个参数
if (client.call(srv))
{
ROS_INFO("sum:%ld",(long int)srv.response.sum);
}
else
{
ROS_ERROR("failed");
return 1;
}
return 0;
}
2.修改cmakelists.txt文件并编译
修改ros_client包内cmakelists.txt内容如下:
###1这句指定了可执行文件的名字为client
#######rosrun的时候和这个文件名字对应
add_executable(client src/client.cpp)
###2
add_dependencies(client client)
###3
target_link_libraries(client ${catkin_LIBRARIES})
和上面ros_service一样 换汤不换药
最后catkin_make一下完成
四、测试
先运行roscore
roscore
再配置环境变量(source一下),之后打开service
rosrun ros_service service
最后运行client(别忘了source一下)
rosrun ros_client client 4 8
这时候你会看到输出,切换到service端会看到调试信息
五、catkin_make编译指定pkg
1.编译指定包
在编译过程中难免出错,修改后建议一个个包编译,
使用命令如下
catkin_make -DCATKIN_WHITELIST_PACKAGES="ros_service"
个人理解为把某个包放入白名单,一执行catkin_make就执行他
注意:使用这个命令后 下一次catkin_make命令也只会编译你列入白名单的包不会全部编译
2.恢复编译所有包
catkin_make -DCATKIN_WHITELIST_PACKAGES=""