【ROS服务通信】服务端和客户端

news2024/9/28 1:23:37

本文记录下ROS服务通信的实现,首先明确,ROS中的服务通信主要适用于偶然的,有实时要求的场景。服务通信基于客户-服务的架构,在主节点下,由服务端和客户端组成,服务端负责对请求做出响应,客户端发出请求和得到响应。

1 定义服务信息,该部分和话题通信中自定义消息的过程非常类似

1.1 新建服务消息类型 srv

在这里插入图片描述
Addints.srv代码内容:
"—"上方为请求信息,下方为响应信息

int32 num1
int32 num2
---
int32 sum
1.2 功能包配置

1 打开 packages.xml ,添加相应的依赖内容即可

  <build_depend>message_generation</build_depend>
   <exec_depend>message_runtime</exec_depend>

在这里插入图片描述
2 打开 CMakeLists.txt,配置相关内容
在这里插入图片描述
对应自定义的服务信息格式文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置好以上信息后,就开始编译项目,然后会发现项目根目录下的 devel 文件夹下,出现了服务信息的编译内容
在这里插入图片描述在这里插入图片描述
然后将生成的编译文件,配置到 c_cpp_properties.json,这个主要是为了能够在C++或Python代码中,能够引到编写的内容。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

源代码工程目录

在这里插入图片描述

C++实现

1 服务端

#include "ros/ros.h"
#include "plumbing_server_client/Addints.h"
/**
 * @brief 
 * 
 * @param argc 
 * @param argv 
 * @return int 
 * 服务端解析服务信息,且作出反应
 * 1 初始化ros节点
 * 2 创建句柄
 * 3 声明一个服务对象
 * 4 处理请求并作出响应
 * 5 spin 循环的话 spin_once()
 */
bool doNums(plumbing_server_client::Addints::Request &request,
plumbing_server_client::Addints::Response &response){
// 1  处理请求
int num1 = request.num1;
int num2 = request.num2;
ROS_INFO("receive the num : %d,%d",num1,num2);
//2 作出响应
int sum = num1 + num2;
response.sum = sum;
ROS_INFO("process result: %d",sum);
return true;
}
int main(int argc,char *argv[]){
    ros::init(argc,argv,"server_01");
    ros::NodeHandle nh;
    ros::ServiceServer server = nh.advertiseService("addints",doNums);
    ROS_INFO("server start...");
    ros::spin();
    return 0;
}

2 客户端代码

#include "ros/ros.h"
#include "plumbing_server_client/Addints.h"
/*
* 服务端解析服务信息,且作出反应
 * 1 初始化ros节点
 * 2 创建句柄
 * 3 声明一个客户端对象
 * 4 处理请求并作出响应
 *优化:动态增加两个参数
 rosrun 包名 节点名 para1 para2

如果客户端先启动,然后服务端再启动,会抛出异常
则如果客户端启动,可先挂起,等服务端启动后再执行
*/
int main(int argc,char *argv[]){
    setlocale(LC_ALL,"");
    //判断是不是3个参数
    if(argc !=3){
        ROS_INFO("paramer num is wrong!");
        return 1;
    }
    ros::init(argc,argv,"client_01");
    ros::NodeHandle nh;
    ros::ServiceClient client =  nh.serviceClient<plumbing_server_client::Addints>("addints");
    //提交请求获取响应
    plumbing_server_client::Addints ai;
    //atoi:char to int 
    ai.request.num1 = atoi(argv[1]);
    ai.request.num2 = atoi(argv[2]);
    //wait  the service start...
    client.waitForExistence();
    //这两个都可
    //ros::service::waitForService("addints");
    //处理响应
    bool flag = client.call(ai);
    if(flag){
        ROS_INFO("process success... %d",ai.response.sum);
    }else{
        ROS_INFO("process false!");
    }
    return 0;
}

3 配置 CMakeLists.txt
在这里插入图片描述
增加节点编译依赖

add_dependencies(server_01_node ${PROJECT_NAME}_gencpp)
add_dependencies(client_01_node ${PROJECT_NAME}_gencpp)

在这里插入图片描述
在这里插入图片描述
4 配置好后,开始运行

roscore#启动主节点

启动服务端

source ./devel/setup.bash
rosrun plumbing_server_client server_01_node

启动客户端

source ./devel/setup.bash
#后面两个数值为传入的num1 和 num2
rosrun plumbing_server_client client_01_node 10 20

Python实现

1 服务端代码

#! /usr/bin/env python
# -*- coding:utf-8 -*-
import rospy
from plumbing_server_client.srv import Addints,AddintsRequest,AddintsResponse
#from plumbing_server_client.srv import *

# 0 导包
# 1 初始化 ros节点
# 2 新建服务端对象
# 3 处理逻辑(回调函数)
# 4 spin()

#封装request对象
def doNum(request):
    num1 = request.num1
    num2 = request.num2

    sum = num1 + num2

    response = AddintsResponse()
    response.sum = sum

    rospy.loginfo("num1 = %d , num2 = %d, response cal : %d", num1, num2, sum)
    return response
if __name__=="__main__":
    rospy.init_node("server_py")
    server = rospy.Service("addints_py",Addints,doNum)
    rospy.loginfo("server have started...")
    rospy.spin()

2 客户端代码

#! /usr/bin/env python
# -*- coding:utf-8 -*-
import rospy
from plumbing_server_client.srv import Addints,AddintsRequest,AddintsResponse
import sys
#对于偶然 实时性要求的场景
#客户端:组织并提交请求,处理服务端响应
# 1 初始化ros节点
# 2 创建客户端对象
# 3 组织请求数据 并发送请求
# 4 处理响应

if __name__=="__main__":
    #sys.argv[0]为文件名称
    if len(sys.argv) != 3:
        rospy.logerr("the paramers number is wrong!")
        sys.exit(1)
    rospy.init_node("client_py")
    client = rospy.ServiceProxy("addints_py",Addints)
    #解析传入的参数
    num1=int(sys.argv[1])
    num2=int(sys.argv[2])
    #client.wait_for_service()
    rospy.wait_for_service("addints_py")
    response = client.call(num1,num2)
    rospy.loginfo("response data:%d",response.sum)

CMakeLists.txt配置
在这里插入图片描述
准备运行:

需要切换到python的脚本文件夹中,更改Python脚本的权限
chmod +x *.py
roscore#启动主节点

启动服务端

source ./devel/setup.bash
rosrun plumbing_server_client server.py

启动客户端

source ./devel/setup.bash
rosrun plumbing_server_client client.py 10 20 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/97188.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL Server2019详细安装教程(含JDBC连接)

文章目录一、安装SQL Server引擎1.1、安装SQL Server1.2、SQL Server选项配置二、SQL Server Management Studio&#xff08;SSMS&#xff0c;客户端&#xff09;2.1、安装连接工具2.2、连接SQL Server三、JDBC连接SQLServer提前配置查看SQLSever的启动端口Java代码参考文章一、…

雷神五代笔记本U盘重装系统图文教程

雷神五代笔记本U盘重装系统图文教程分享。有用户使用的雷神五代笔记本开机之后会自动安装很多的软件&#xff0c;导致卡到无法正常使用。这个情况是电脑中了病毒程序导致的&#xff0c;一起来看看如何通过U盘来重新安装系统操作教程吧。 准备工作&#xff1a; 1、U盘一个&#…

蓝桥杯嵌入式串口uart

文章目录前言一、板子串口原理图2.cubeMx配置3.波特率的简单讲解4.代码编写一、发送数据函数二、开启接收中断函数三、中断回调函数四、具体使用总结前言 本篇文章将带大家了解串口的编程&#xff0c;串口在比赛当中和实际工程中都是非常重要的&#xff0c;串口的难度也比较大…

微信小程序自定义tabbar底部菜单

自定义 tabBar 可以让开发者更加灵活地设置 tabBar 样式&#xff0c;以满足更多个性化的场景。 在自定义 tabBar 模式下&#xff0c;为了保证低版本兼容以及区分哪些页面是 tab 页&#xff0c;tabBar 的相关配置项需完整声明&#xff0c;但这些字段不会作用于自定义 tabBar 的渲…

UC伯克利提出AIGC图像编辑新利器InstructPix2Pix,AI模型P图更加精细

原文链接&#xff1a;https://www.techbeat.net/article-info?id4375 作者&#xff1a;seven_ 最近的一些工作向我们展示了AIGC在创造性生成图像、视频等方面的潜力&#xff0c;相信已有很多研究者在沿着这一方向进行拓展式的挖掘和创新。目前已有很多衍生应用出现在了大家眼前…

Java中的类和对象

文章目录1.面向对象和面向过程的含义2.类的定义与使用2.1什么是类2.2类的定义和格式2.3类名的修改方法![在这里插入图片描述](https://img-blog.csdnimg.cn/f126dbd47491402e93bc83bc07f51673.png)3.类和对象3.1类的实例化3.2成员的访问4.this引用4.1为何要this引用4.2什么是th…

java和vue的学生健康管理系统疫情打卡系统

需求&#xff1a;关注学生健康数据以及疫情打卡 系统分两个角色&#xff1a;学生和管理员 演示视频 https://www.bilibili.com/video/BV1iD4y1h74F/?share_sourcecopy_web&vd_sourceed0f04fbb713154db5cc611225d92156 技术&#xff1a;springbootvueelementuipagehelperm…

医疗器械实验室设计基本要求SICOLAB

医疗器械实验室设计基本要求SICOLAB 医疗器械实验室设计、医疗器械实验室装修、医疗器械实验室建设SICOLAB 一、实验室分类 &#xff08;一&#xff09;基础实验室 生物学评价检验实验室、电气安全检验实验室、环境试验检验实验室、手术医疗器械检验实验室、医用材料检验实…

【图像去噪】双立方插值和稀疏表示图像去噪【含Matlab源码 2009期】

⛄一、稀疏表示模型简介 图像的稀疏表示能够更好地表示出图像的特征, 其理论依据就是, 有用的图像信号是有序的, 而噪声普遍是杂乱无章的, 因此可以提取出能够表示图像特有奇异性特征的信息, 比如边缘、线段、条纹、端点等, 再用特定的过完备字典中的原子进行线性组合, 重构出…

JDK的安装及环境变量配置

一、应用安装 1、可以在官网下载jdk&#xff0c;&#xff08;http://www.oracle.com/&#xff09;下载自己适用的版本。 2、双击下载的 .exe安装包文件,如 jdk-8u131-windows-x64.exe。 3、进入安装向导。 4、点击下一步&#xff0c;更改安装路径&#xff0c;我选择安装在d盘…

30分钟看懂linux内核 - page介绍

【推荐阅读】 浅析linux内核网络协议栈--linux bridge 深入理解SR-IOV和IO虚拟化 了解Docker 依赖的linux内核技术 浅谈linux 内核网络 sk_buff 之克隆与复制 深入linux内核架构--进程&线程 内核中最初勾引我好奇心的还是内存管理方面&#xff0c;我们平时编写应用程…

代码随想录训练营第53天|LeetCode 1143.最长公共子序列、1035.不相交的线、53. 最大子序和

参考 代码随想录 题目一&#xff1a;LeetCode 1143.最长公共子序列 确定dp数组下标及其含义 dp[i][j]&#xff1a;字符串text1中的0&#xff5e;i字符构成的字符串和字符串text2中的0&#xff5e;j字符构成的字符串的最长 公共子序列 的长度为dp[i][j]。注意和之前做过的Leet…

将postgresql配置为Linux服务管理 systemctl service

发行版安装的数据库在装完后会自动添加数据库服务&#xff0c;但编译安装的不会&#xff0c;需要手动添加。 cd postgresql-14.0/contrib/start-scripts/ cp linux /etc/init.d/postgresql cd /etc/init.d/ vi postgresql 修改以下部分 ## EDIT FROM HERE# Installation pre…

Vuex4.0.0 源码解析

本文章基于以下版本撰写 VUE 版本&#xff1a; 3.0VUEX 版本&#xff1a;4.0.0Vuex仓库&#xff1a;https://github.com/vuejs/vuex/tree/v4.0.0Vux文档&#xff1a;https://vuex.vuejs.org/zh/ 在 vue 中使用 vuex import { createApp } from vue import { createStore } f…

C语言中函数的先后关系,java和C语言的语法区别

以上代码中&#xff0c;sum函数在上面&#xff0c;main函数在下面&#xff0c;在main函数中就可以调用sum函数。 如果sum函数定义在main函数后面&#xff0c;则需要在main函数前面声明sum函数。即在main函数前面写&#xff1a;void sum(int begin, int end); C语言中&#xf…

EMC测试中的电流探头

专栏 专注介绍电磁兼容&#xff08;EMC&#xff09;的相关知识&#xff0c;算是对本人浸染 EMC 专业十余年的一个阶段小结 。 本文目录1.EMC测试中的电流探头是什么&#xff1f;2.电流探头的主要指标要求3.什么是转移阻抗&#xff1f;1.EMC测试中的电流探头是什么&#xff1f; …

校园兼职网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 网站前台&#xff1a;关于我们、联系我们、资讯信息、企业信息、职位信息 管理员模块&#xff1a; 1、管理关于我们、联…

vTESTstudio入门到精通 - vTESTstudio工具栏介绍_File

vTESTstudio作为跟CANoe工具并套使用的一个强大的工具&#xff0c;那么想要用好它就得对他有个全面的认识&#xff0c;第一步起码要知道tade工具栏都包含哪些功能要清楚&#xff0c;今天我们就着重分享下vTESTstudio工具栏包含哪些内容&#xff0c;以便在我们编程的时候更好的去…

java 瑞吉外卖day2 笔记 员工增加 员工信息分页查询

PostMapping public R save(HttpServletRequest request,RequestBody Employee employee){log.info("新增员工&#xff1a;{}",employee);//设置初始密码123456 需要进行md5加密employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));em…

homeassistant 接入小米温湿度计2

方法可能有很多种&#xff0c;但是我只用这种方法介入成功了 环境&#xff1a; - 香橙派&#xff08;自带蓝牙&#xff0c;树莓派应该也可以&#xff09; - 小米温湿度计2 - 网站&#xff1a;Telink Flasher v4.7 、 Telink Flasher (atc1441.github.io) - 固件&#xff1…