【古月居《ros入门21讲》学习笔记】13_服务数据的定义与使用

目录

说明:

1. 服务模型

2. 实现过程(C++)

自定义服务数据

Person.srv文件内容

Person.srv文件内容说明

编译配置

在package.xml文件中添加功能包依赖

在CMakeLists.txt中添加编译选项

编译生成语言相关文件

创建服务器代码(C++)

创建客户端代码(C++)

配置服务器/客户端代码编译规则

编译并运行

编译

运行

3. 实现过程(Python)

创建服务器代码(Python)

创建客户端代码(Python)

运行


说明:

1. 本系列学习笔记基于B站:古月居《ROS入门21讲》课程,且使用的Ubuntu与ROS系统版本与课程完全一致;

虚拟机版本Linux系统版本ROS系统版本
VMware WorkStation Pro 16Ubuntu18.04Melodic

2. 课程中的所有示例代码均已跑通,且对Pyhon版本的代码也都做了运行验证,并附带验证过程(错误均已修正);

3. 本节是整个笔记的第13节,对应视频课程的第15节,请自行对应学习;

4. 整个系列笔记基本已经完结,但部分章节仍需润色修改 ,后面会陆续发布,请大家持续关注,      创作不易,感谢支持!


1. 服务模型

image-20230602144618868

2. 实现过程(C++)

自定义服务数据

cd ~/catkin_ws/src/learning_service
mkdir srv
cd srv
touch Person.srv

Person.srv文件内容
string name // 名字
uint8 age   // 年龄
uint8 sex   // 性别:分为3种,男、女、未知,下面以012宏定义做表示判断
​
uint8 unknown = 0 
uint8 male = 1    
uint8 female = 2
---
string result
Person.srv文件内容说明

Person.msg文件里定义的内容跟语言无关的,这既不是c++,也不是python,这里面的string uint8表示在不同的程序里面扩展成对应该种程序的表示方法,可以类比单片机里无符号整型变量类型unsigned int来理解,缩写就是uint。---上面是request的内容,下面是response的内容。

cd ~/catkin_ws/src/learning_service
mkdir srv

注意:新建的这个文件夹名字不能随便命名,只能叫srv,否则编译会报错,CMakeList文件中有说明,要放在名叫srv文件夹中。

image-20230605091153427

cd srv
touch Person.srv

(注意:这里的文件名首字母P一定要大写!否则后面会报错)

打开Person.srv文件,把定义的内容复制到文件里并保存,

(注意:输入的内容中,注释不要,空格不能用tab键缩进,否则后面也会报错)

image-20230605091423508

编译配置

路径:~/catkin_ws/src/learning_service

在package.xml文件中添加功能包依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

build_depend:编译依赖

exec_depend:运行依赖

image-20230605092006300

在CMakeLists.txt中添加编译选项
find_package(......message_generation)

image-20230605092608776

add_service_files(FILES Person.srv)
generate_messages(DEPENDENCIES std_msgs)

add_service_files: 把我们定义的Person.srv文件,做为我们定义的接口;

generate_messages:编译Person.srv文件的时候需要用到一些依赖于ROS已有的库或包,

我们这里用到的依赖是std_msgs,我们前面看到的string,uint8都是在std_msgs里面做定义的

image-20230605092905121

catkin_package(......message_runtime)

image-20230605093653372

编译生成语言相关文件
cd ~/catkin_ws
catkin_make

image-20230605094013216

编译成功之后可以在~/catkin_ws/devel/include/learning_service下看到Person.srv文件编译生成的C++的三个头文件

Person.hPersonRequest.hPersonResponse.h

image-20230605094516308

创建服务器代码(C++)

cd ~/catkin_ws/src/learning_service/src
touch person_server.cpp

  • 初始ROS化节点;

  • 创建Server实例;

  • 循环等待服务器请求,进入回调函数;

  • 在回调函数中完成服务功能的处理,并反馈应答数据

/*** 该例程将执行/show_person服务,服务数据类型learning_service::Person*/#include <ros/ros.h>
#include "learning_service/Person.h"
​
// service回调函数,输入参数req,输出参数res
bool personCallback(learning_service::Person::Request  &req,learning_service::Person::Response &res)
{// 显示请求数据ROS_INFO("Person: name:%s  age:%d  sex:%d", req.name.c_str(), req.age, req.sex);
​// 设置反馈数据res.result = "OK";
​return true;
}
​
int main(int argc, char **argv)
{// ROS节点初始化ros::init(argc, argv, "person_server");
​// 创建节点句柄ros::NodeHandle n;
​// 创建一个名为/show_person的server,注册回调函数personCallbackros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);
​// 循环等待回调函数ROS_INFO("Ready to show person informtion.");ros::spin();
​return 0;
}
​

image-20230605095546641

创建客户端代码(C++)

cd ~/catkin_ws/src/learning_service/src
​
touch person_client.cpp

  • 初始化ros节点;

  • 创建一个Client实例;

  • 发布服务请求数据;

  • 等待Server处理之后的应答结果。

/*** 该例程将请求/show_person服务,服务数据类型learning_service::Person*/
​
#include <ros/ros.h>
#include "learning_service/Person.h"
​
int main(int argc, char** argv)
{// 初始化ROS节点ros::init(argc, argv, "person_client");
​// 创建节点句柄ros::NodeHandle node;
​// 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的serviceros::service::waitForService("/show_person");ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person");
​// 初始化learning_service::Person的请求数据learning_service::Person srv;srv.request.name = "Tom";srv.request.age  = 20;srv.request.sex  = learning_service::Person::Request::male;
​// 请求服务调用ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]", srv.request.name.c_str(), srv.request.age, srv.request.sex);
​person_client.call(srv);
​// 显示服务调用结果ROS_INFO("Show person result : %s", srv.response.result.c_str());
​return 0;
};
​
​

image-20230605100114690

配置服务器/客户端代码编译规则

add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)
​
add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)

image-20230605100614365

编译并运行

编译
cd ~/catkin_ws
​
catkin_make
​
source devel/setup.bash(如已配置 **.bashrc**文件,则此步不需要,配置方法在publisher的章节里)

image-20230605101139615

运行
roscore
rosrun learning_service person_server
rosrun learning_service person_client

image-20230605101940210

3. 实现过程(Python)

创建服务器代码(Python)

cd ~/catkin_ws/src/learning_service/scripts
touch person_server.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将执行/show_person服务,服务数据类型learning_service::Person
​
import rospy
from learning_service.srv import Person, PersonResponse
​
def personCallback(req):# 显示请求数据rospy.loginfo("Person: name:%s  age:%d  sex:%d", req.name, req.age, req.sex)
​# 反馈数据return PersonResponse("OK")
​
def person_server():# ROS节点初始化rospy.init_node('person_server')
​# 创建一个名为/show_person的server,注册回调函数personCallbacks = rospy.Service('/show_person', Person, personCallback)
​# 循环等待回调函数print "Ready to show person informtion."rospy.spin()
​
if __name__ == "__main__":person_server()
​
​

image-20230605110437598

创建客户端代码(Python)

cd ~/catkin_ws/src/learning_service/scripts
touch person_client.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型learning_service::Person
​
import sys
import rospy
from learning_service.srv import Person, PersonRequest
​
def person_client():# ROS节点初始化rospy.init_node('person_client')
​# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的servicerospy.wait_for_service('/show_person')try:person_client = rospy.ServiceProxy('/show_person', Person)
​# 请求服务调用,输入请求数据response = person_client("Tom", 20, PersonRequest.male)return response.resultexcept rospy.ServiceException, e:print "Service call failed: %s"%e
​
if __name__ == "__main__":#服务调用并显示调用结果print "Show person result : %s" %(person_client())
​
​

image-20230605110720376

注意:给person_server.py 和 person_client.py文件赋予作为程序文件执行的权限,

点击person_server.py文件,右键,属性,权限,勾选(允许作为程序文件执行),

person_client.py文件操作同上,python文件不需要编译,直接运行即可。

image-20230605111042830

运行

roscore
rosrun learning_service person_server.py
rosrun learning_service person_client.py

image-20230605111501592


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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊云科技Aurora MySQL在复制性能提升上的不断优化和尝试

前言 Amazon Aurora是亚马逊云科技自研的云原生关系数据库&#xff0c;它在提供和开源数据库MySQL、PostgreSQL的完好兼容性同时&#xff0c;也能够提供和商业数据库媲美的性能和可用性。 Aurora的性能提升不仅包含应用读写吞吐量的提升&#xff0c;也包含复制延迟的降低。一个…

【算法刷题】Day8

文章目录 202. 快乐数解法&#xff1a; 11. 盛最多水的容器解法&#xff1a; 202. 快乐数 原题链接 拿到题&#xff0c;我们先看题干 把一个整数替换为每个位置上的数字平方和&#xff0c;有两种情况&#xff1a; 重复这个过程始终不到 1&#xff08;无限死循环&#xff09;结…

移动应用开发介绍及iOS方向学习路线(HUT移动组版)

移动应用开发介绍及iOS方向学习路线&#xff08;HUT移动组版&#xff09; 前言 ​ 作为一个HUT移动组待了一坤年&#xff08;两年半&#xff09;多的老人&#xff0c;在这里为还在考虑进哪个组的萌新们以及将来进组的新朋友提供一份关于移动应用开发介绍以及学习路线的白话文…

Leetcode—2336.无限集中的最小数字【中等】

2023每日刷题&#xff08;四十四&#xff09; Leetcode—2336.无限集中的最小数字 实现代码 class SmallestInfiniteSet {set<int> s; public:SmallestInfiniteSet() {for(int i 1; i < 1000; i) {s.insert(i);}}int popSmallest() {int res *s.begin();s.erase(s…

2023年的 Web 前端开发建议需要具备技能

2023年的 Web 前端开发需要具备一系列技能&#xff0c;以应对不断变化的技术环境和满足日益增长的业务需求。以下是一些可能被视为必备的技能&#xff0c;以及为什么这些技能在当今前端开发中显得至关重要&#xff1a; 一、JavaScript、HTML、CSS&#xff1a; 为什么重要&…

盘点67个Android系统源码安卓爱好者不容错过

盘点67个Android系统源码安卓爱好者不容错过 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 源码下载链接&#xff1a;https://pan.baidu.com/s/1zOSFwPJwDJLFfoeRJy9llg?pwd8888 提取码&#xff1a;8888 项目名称 Accelera…

数字人透明屏幕的技术原理是什么?

数字人透明屏幕的技术原理主要包括人脸识别和全息影像技术。其中&#xff0c;人脸识别技术是通过摄像头捕捉游客的面部表情和动作&#xff0c;并将其转化为数据指令&#xff0c;以便与数字人物进行互动。而全息影像技术则是利用透明屏幕&#xff0c;通过全息投影的方式将数字人…

10k热敏电阻温度对照表

10k热敏电阻阻值温度对数图 10k热敏电阻温度对照表 温度&#xff08;℃&#xff09;欧姆 -4033660033660-3931500031500-3829500029500-3727640027640-3625900025900-3524280024280-3422780022780-3321380021380-3220060020060-3118840018840-3017700017700-2916640016640-28…

HCIP --- MGRE综合实验

一、总体规划 二、AR1配置思路及步骤 一、接口地址分配及缺省路由&#xff1a; The device is running! AR1&#xff1a; <Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]sy r1 [r1]interface s4/0/0 [r1-Serial4/0/0]ip address 15.0.0.1 255.0…

Spark---SparkCore(五)

五、Spark Shuffle文件寻址 1、Shuffle文件寻址 1&#xff09;、MapOutputTracker MapOutputTracker是Spark架构中的一个模块&#xff0c;是一个主从架构。管理磁盘小文件的地址。 MapOutputTrackerMaster是主对象&#xff0c;存在于Driver中。MapOutputTrackerWorker是从对…

五分钟 k8s 实战-应用探针

Probe.png 今天进入 kubernetes 的运维部分&#xff08;并不是运维 kubernetes&#xff0c;而是运维应用&#xff09;&#xff0c;其实日常我们大部分使用 kubernetes 的功能就是以往运维的工作&#xff0c;现在云原生将运维和研发关系变得更紧密了。 今天主要讲解 Probe 探针相…

source: command not found错误的解决方法

偶遇的一个问题&#xff0c;因为在网上没有找到对应的解决办法&#xff0c;可能是属于个案&#xff0c;在此记录备忘&#xff0c;同时供大家参考。 问题现象&#xff1a; 执行命令 source /etc/profile时报错&#xff1a; bash: “source: command not found... 问题定位和…