当前位置 博文首页 > 自定义srv调用实现(C++)_txr152111的博客:16th 服务通信
15th 服务通信自定义srv | 生成头文件
目标:
编写服务通信,客户端提交两个整数至服务端,服务端求和并响应结果到客户端。
分析:
在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
不配置也是可以的,但是不能再vscode中代码自动补齐,且导报时VSCode会报错,但是不影响最终程序的运行,建议配置。
?
?使用pwd获得到路径。
添加路径:
#include<ros/ros.h>
#include<plumbing_server_client/Addints.h>
/*
服务端实现:解析客户端提交的数据,并运算再返回相应
1.包含头文件
2.初始化ros节点
3.创建节点句柄
4.创建一个服务对象
5.处理并产生相应
6.spin()
*/
bool doNum(plumbing_server_client::Addints::Request &request,
plumbing_server_client::Addints::Response &response)
{
//1.处理请求
int num1 = request.num1;
int num2 = request.num2;
ROS_INFO("收到的请求数据:num1 = %d,num2 = %d",num1,num2);
//2.组织响应
int sum = num2+num1;
response.sum = sum;
ROS_INFO("求得的结果为:sum = %d",sum);
return true;
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
// 2.初始化ros节点
ros::init(argc,argv,"gongsi"); //设置节点名,为gongsi
// 3.创建节点句柄
ros::NodeHandle nh;
// 4.创建一个服务对象
ros::ServiceServer server = nh.advertiseService("AddInts",doNum);
ROS_INFO("服务器端已启动");
// 5.处理并产生相应
// 6.spin()
ros::spin();
return 0;
}
在CMakelist.txt文件中:
编译:Ctrl + Shift + B
rosservice? call? AddInts? ?Tab键补齐
#include<ros/ros.h>
#include<plumbing_server_client/Addints.h>
/*
客户端:提交两个整数,并处理响应的结果(打印出来即可)
1.包含头文件
2.初始化ros节点
3.创建节点句柄
4.创建一个客户端对象
5.提交请求并处理相应
没有回调函数,spin()就可有可无了
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
// 2.初始化ros节点
ros::init(argc,argv,"DaBao");
// 3.创建节点句柄
ros::NodeHandle nh;
// 4.创建一个客户端对象
ros::ServiceClient client = nh.serviceClient<plumbing_server_client::Addints>("AddInts");
// 5.提交请求并处理相应
//5.1组织请求
plumbing_server_client::Addints ai;
ai.request.num1 = 100;
ai.request.num2 = 200;
//5.2处理响应
client.call(ai);
bool flag = client.call(ai);
if (flag = true)
{
ROS_INFO("响应成功!");
ROS_INFO("响应结果=%d",ai.response.sum);
}
else
{
ROS_INFO("处理失败!");
}
return 0;
}
CMakelists.txt文件中:
?编译:Ctrl + Shift + B
?测试:
这上面的例程中,num1和num2都是固定死的,如何实现那种任意输入的参数呢,实现参数的动态提交。格式: rosrun ?包名 ?节点名 ?num1 ?num2
#include<ros/ros.h>
#include<plumbing_server_client/Addints.h>
/*
客户端:提交两个整数,并处理响应的结果(打印出来即可)
1.包含头文件
2.初始化ros节点
3.创建节点句柄
4.创建一个客户端对象
5.提交请求并处理相应
没有回调函数,spin()就可有可无了
实现参数的动态提交:
1.格式: rosrun 包名 节点名 num1 num2
2.节点执行时,需要获取命令中的参数,并赋值入request
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//优化实现,获取命令中的参数
if (argc != 3)
{
ROS_INFO("提交的参数个数不对");
return 1;
}
// 2.初始化ros节点
ros::init(argc,argv,"DaBao");
// 3.创建节点句柄
ros::NodeHandle nh;
// 4.创建一个客户端对象
ros::ServiceClient client = nh.serviceClient<plumbing_server_client::Addints>("AddInts");
// 5.提交请求并处理相应
//5.1组织请求
plumbing_server_client::Addints ai;
ai.request.num1 = atoi(argv[1]);
ai.request.num2 = atoi(argv[2]); //atoi,将字符串类型转换为整数类型
//5.2处理响应
client.call(ai);
bool flag = client.call(ai);
if (flag = true)
{
ROS_INFO("响应成功!");
ROS_INFO("响应结果=%d",ai.response.sum);
}
else
{
ROS_INFO("处理失败!");
}
return 0;
}
?运行测试:
如果先启动客户端,那么会导致运行失败,但是现在就需要先启动客户端,并且要求正常挂起,如何实现?
优化:
在客户端发送请求前添加:client.waitForExistence();
或:ros::service::waitForService("AddInts");? ?需要传一个参数,为服务的话题名。
这是一个阻塞式函数,只有服务启动成功后才会继续执行
此处可以使用 launch 文件优化,但是需要注意 args 传参特点
?
cs