自定义srv
# 客户端请求时发送的两个数字
int32 num1
int32 num2
---
# 服务器响应发送的数据
int32 sum
string strs
编辑配置文件
package.xml中添加编译依赖与执行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<!--
exce_depend 以前对应的是 run_depend 现在非法
-->
CMakeLists.txt编辑 srv 相关配置
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
# 需要加入 message_generation,必须有 std_msgsadd_service_files(
FILES
AddInts.srv
)generate_messages(
DEPENDENCIES
std_msgs
)
服务端C++
/*
需求:
编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
客户端再解析
服务器实现:
1.包含头文件
2.初始化 ROS 节点
3.创建 ROS 句柄
4.创建 服务 对象
5.回调函数处理请求并产生响应
6.由于请求有多个,需要调用 ros::spin()
*/
#include "ros/ros.h"
#include "learning_client_server/AddInts.h"
#include <string>
// 回调函数,返回值由于标志是否处理成功
bool doReq(learning_client_server::AddInts::Request& req,
learning_client_server::AddInts::Response& resp){
int num1 = req.num1;
int num2 = req.num2;
ROS_INFO("服务器收到的请求数据为: %d , %d ",num1,num2);
if(num1<0||num2<0){
ROS_ERROR("提交的请求数据异常:数据不可以为负数");
return false;
}
// 结果复制给resp
resp.sum = num1+num2;
std::string str = "两个数的和是:";
resp.strs = str;
return true;
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
// 2.初始化 ROS 节点
ros::init(argc,argv,"besproma_server");
// 3.创建 ROS 句柄
ros::NodeHandle nh;
// 4.创建 服务 对象
ros::ServiceServer server = nh.advertiseService("besproma_CSAddInt",doReq);
ROS_INFO("服务器已经启动");
ros::spin();
return 0;
}
客户端C++
/*
需求:
编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
客户端再解析
服务器实现:
1.包含头文件
2.初始化 ROS 节点
3.创建 ROS 句柄
4.创建 客户端 对象
5.请求服务,接收响应
6.发送请求,返回 bool 值,标记是否成功
7.处理响应
*/
#include "ros/ros.h"
#include "learning_client_server/AddInts.h"
int main(int argc, char*argv[])
{
setlocale(LC_ALL,"");
if(argc!=3){
ROS_INFO("提交的参数个数不对..");
return 1;
}
// 2.初始化 ROS 节点
ros::init(argc,argv,"besproma_client");
// 3.创建 ROS 句柄
ros::NodeHandle nh;
// 4.创建 客户端 对象
ros::ServiceClient client = nh.serviceClient<learning_client_server::AddInts>("besproma_CSAddInt");
// 等待服务启动成功
//方式1
ros::service::waitForService("besproma_CSAddInt");
//方式2
// client.waitForExistence();
// 5.请求服务,接收响应
learning_client_server::AddInts addint;
addint.request.num1 = atoi(argv[1]);
addint.request.num2 = atoi(argv[2]);
// 6.发送请求,返回 bool 值,标记是否成功
bool flag = client.call(addint);
// 7.处理响应
if(flag){
ROS_INFO("请求正常处理,响应结果: %s %d", addint.response.strs.c_str(), addint.response.sum);
}else{
ROS_ERROR("请求处理失败....");
return 1;
}
return 0;
}
客户端python
#! /usr/bin/env python
"""
需求:
编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
客户端再解析
客户端实现:
1.导包
2.初始化 ROS 节点
3.创建请求对象
4.发送请求
5.接收并处理响应
优化:
加入数据的动态获取
"""
import learning_client_server
import rospy
from learning_client_server.srv import *
import sys
if __name__=="__main__":
if len(sys.argv) != 3:
rospy.logerr("请正确提交参数")
sys.exit(1)
# 2.初始化 ROS 节点
rospy.init_node("besproma_client_py")
# 3.创建请求对象
client = rospy.ServiceProxy("besproma_CSAddInt",AddInts)
client.wait_for_service()
req = AddIntsRequest()
req.num1 = int(sys.argv[1])
req.num2 = int(sys.argv[2])
resp = client.call(req)
rospy.loginfo("响应结果: %s %d",resp.strs,resp.sum)
服务端python
#! /usr/bin/env python
"""
需求:
编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
客户端再解析
服务器端实现:
1.导包
2.初始化 ROS 节点
3.创建服务对象
4.回调函数处理请求并产生响应
5.spin 函数
"""
import rospy
from learning_client_server.srv import AddInts,AddIntsRequest,AddIntsResponse
def doReq(req):
sum = req.num1+req.num2
rospy.loginfo("提交的数据:num1 = %d, num2 = %d, sum = %d",req.num1, req.num2, sum)
# 创建响应对象,赋值并返回
resp = AddIntsResponse()
resp.sum = sum
resp.strs = "和为: "
return resp
if __name__=="__main__":
# 2.初始化 ROS 节点
rospy.init_node("besproma_serve_py")
# 3.创建服务对象
server = rospy.Service("besproma_CSAddInt",AddInts,doReq)
# 4.回调函数处理请求并产生响应
# 5.spin 函数
rospy.spin()
实验可知:若两个相同话题的服务端同时存在,后启动的服务端会取代先启动的服务端,先启动的服务端失效,但是没有报错。