自定义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()

实验可知:若两个相同话题的服务端同时存在,后启动的服务端会取代先启动的服务端,先启动的服务端失效,但是没有报错。