ROS1学习笔记:服务中的Service和Client(ubuntu20.04)

news2024/9/23 7:22:06

参考B站古月居ROS入门21讲:
客户端Client的编程实现
服务端Server的编程实现
基于VMware Ubuntu 20.04 Noetic版本的环境

文章目录

  • 一、小乌龟例程中的服务
  • 二、创建功能包
  • 三、创建Client代码
    • 3.1 以C++为例
      • 3.1.1 配置Client代码编译规则
      • 3.1.2 编译整个工作空间
      • 3.1.3 配置环境变量
      • 3.1.4 执行代码
    • 3.2 以Python为例
      • 3.2.1 配置Client代码编译规则
      • 3.2.2 编译整个工作空间
      • 3.2.3 配置环境变量
      • 3.2.4 执行代码
  • 四、创建Server代码
    • 4.1 以C++为例
      • 4.1.1 配置Server代码编译规则
      • 4.1.2 编译整个工作空间
      • 4.1.3 配置环境变量
      • 4.1.4 执行代码
    • 4.2 以Python为例
      • 4.2.1 配置Server代码编译规则
      • 4.2.2 编译整个工作空间
      • 4.2.3 配置环境变量
      • 4.2.4 执行代码

服务(Service)是节点之前同步通信的一种方式,允许客户端(Client)节点发布请求(Request),由服务端(Server)节点处理后反馈应答(Response)。

一、小乌龟例程中的服务

小乌龟例程提供了不少设置功能,这些设置都以服务的形式提供。在小乌龟例程运行状态下,使用如下命令查看系统中的服务列表:

rosservice list

在这里插入图片描述
可以使用代码或终端对列表中的服务进行调用。例如使用以下命令调用"/spawn"服务新生一只小乌龟:

rosservice call /spawn "x: 1.0
y: 5.0
theta: 0.0
name: 'turtle2'" 

服务的请求数据是新生小乌龟的位置、姿态以及名称,调用成功后仿真器中就会诞生一只新的小乌龟。如图所示:
在这里插入图片描述
终端会打印服务反馈的应答数据,即新小乌龟的名称,如图所示:
在这里插入图片描述
从小乌龟仿真例程中的服务可以看到,服务一般分为服务端(Server)和客户端(Client)两个部分,Client负责发布请求数据,等待Server处理;Server负责处理相应的功能,并且返回应答数据。
我们来分析一下小海龟仿真器服务模型中的客户端和服务器:

Sever是小海龟仿真器/turtlesimClient端产生Request的请求,发给Server端。Server端收到Request请求后产生一只小海龟,反馈一个ResponseClient小海龟产生是否成功。Service的名称为/spawn,中间传输消息的数据结构为turtlesim::SpawnServer端本身是进行模拟海龟运动的命令端,它的实现是通过给海龟发送速度(Twist)的指令,来控制海龟运动(本身通过Topic实现)。

在这里插入图片描述

Client相当于海龟运动的开关,其发布Request来控制Server端。 通过自定义名为 /turtle_commandService实现,中间传输消息的数据类型为std_srvs::Trigger(一种针对服务标准std_srvs下的数据定义)来通信。Trigger意为触发,通过Trigger信号来触发Server端的运动指令。Server端接收这个Trigger信号后,可控制其是否要给海龟发送Twist指令,同时给Client端发送Response反馈告诉它海龟的运动状态。

在这里插入图片描述

整个节点之间的通讯是在ROS Master下进行的。

二、创建功能包

在本节我们将创建一个新的功能包,名字为learning_service,并创建依赖,复制下面命令即可:

cd ~/catkin_ws/src
catkin_create_pkg learning_service roscpp rospy std_msgs geometry_msgs turtlesim

在这里插入图片描述

三、创建Client代码

如何实现一个客户端Client?

  • 初始化ROS
  • 创建一个Client实例
  • 发布服务请求数据
  • 等待Server处理之后的应答结果

3.1 以C++为例

将代码turtle_spawn.cpp拷贝进src文件夹下:
完整代码为:

/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/

/**
 * 该例程将请求/spawn服务,服务数据类型turtlesim::Spawn
 */

#include <ros/ros.h>
#include <turtlesim/Spawn.h>

int main(int argc, char** argv)
{
    // 初始化ROS节点
	ros::init(argc, argv, "turtle_spawn");

    // 创建节点句柄
	ros::NodeHandle node;

    // 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
	ros::service::waitForService("/spawn");
	ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");

    // 初始化turtlesim::Spawn的请求数据
	turtlesim::Spawn srv;
	srv.request.x = 2.0;
	srv.request.y = 2.0;
	srv.request.name = "turtle2";

    // 请求服务调用
	ROS_INFO("Call service to spwan turtle[x:%0.6f, y:%0.6f, name:%s]", 
			 srv.request.x, srv.request.y, srv.request.name.c_str());

	add_turtle.call(srv);

	// 显示服务调用结果
	ROS_INFO("Spwan turtle successfully [name:%s]", srv.response.name.c_str());

	return 0;
};

3.1.1 配置Client代码编译规则

配置CMakeLists.txt编译规则:

  • 设置需要编译的代码和生成的可执行文件;
  • 设置链接库;

将以下代码复制进去:

add_executable(turtle_spawn src/turtle_spawn.cpp)
target_link_libraries(turtle_spawn ${catkin_LIBRARIES})

在这里插入图片描述

3.1.2 编译整个工作空间

cd ~/catkin_ws
catkin_make

编译完成后能看到/debel/lib/learning_service目录下新生成的可执行文件:
在这里插入图片描述

3.1.3 配置环境变量

之前已经配置过。

3.1.4 执行代码

roscore
rosrun turtlesim turtlesim_node
rosrun learning_service turtle_spawn

可以看到生成了第二只小海龟。
在这里插入图片描述

3.2 以Python为例

将代码turtle_spawn.py拷贝进新建立的scripts文件夹下(别忘了开启执行权限),完整代码为:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
########################################################################

# 该例程将请求/spawn服务,服务数据类型turtlesim::Spawn

import sys
import rospy
from turtlesim.srv import Spawn

def turtle_spawn():
	# ROS节点初始化
    rospy.init_node('turtle_spawn')

	# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
    rospy.wait_for_service('/spawn')
    try:
        add_turtle = rospy.ServiceProxy('/spawn', Spawn)

		# 请求服务调用,输入请求数据
        response = add_turtle(2.0, 2.0, 0.0, "turtle2")
        return response.name
    except rospy.ServiceException as e:
        print(f"Service call failed: {e}")

if __name__ == "__main__":
	#服务调用并显示调用结果
    print(f"Spwan turtle sucessfully [name:{turtle_spawn()}]")

3.2.1 配置Client代码编译规则

打开CMakeLists.txt文件,配置Python代码编译规则:
在这里插入图片描述

3.2.2 编译整个工作空间

cd ~/catkin_ws
catkin_make

3.2.3 配置环境变量

之前已经配置过。

3.2.4 执行代码

roscore
rosrun turtlesim turtlesim_node
rosrun learning_service turtle_spawn.py

在这里插入图片描述

四、创建Server代码

如何实现一个服务器端Server?

  • 初始化ROS
  • 创建一个Server实例
  • 循环等待服务请求,进入回调函数
  • 在回调函数中完成服务功能的处理,并反馈应答数据

4.1 以C++为例

将代码turtle_command_server.cpp拷贝进src文件夹下:
完整代码为:

/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/

/**
 * 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger
 */
 
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <std_srvs/Trigger.h>

ros::Publisher turtle_vel_pub;
bool pubCommand = false;

// service回调函数,输入参数req,输出参数res
bool commandCallback(std_srvs::Trigger::Request  &req,
         			std_srvs::Trigger::Response &res)
{
	pubCommand = !pubCommand;

    // 显示请求数据
    ROS_INFO("Publish turtle velocity command [%s]", pubCommand==true?"Yes":"No");

	// 设置反馈数据
	res.success = true;
	res.message = "Change turtle command state!";

    return true;
}

int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "turtle_command_server");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个名为/turtle_command的server,注册回调函数commandCallback
    ros::ServiceServer command_service = n.advertiseService("/turtle_command", commandCallback);

	// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
	turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);

    // 循环等待回调函数
    ROS_INFO("Ready to receive turtle command.");

	// 设置循环的频率
	ros::Rate loop_rate(10);

	while(ros::ok())
	{
		// 查看一次回调函数队列
    	ros::spinOnce();
		
		// 如果标志为true,则发布速度指令
		if(pubCommand)
		{
			geometry_msgs::Twist vel_msg;
			vel_msg.linear.x = 0.5;
			vel_msg.angular.z = 0.2;
			turtle_vel_pub.publish(vel_msg);
		}

		//按照循环频率延时
	    loop_rate.sleep();
	}

    return 0;
}

在回调函数中给Client端的反馈数据res是与Trigger相对应的,我们可以查看一下Trigger的数据结构。可以使用rossrv指令查看service中的数据类型:

rossrv show std_srvs/Trigger

在这里插入图片描述

4.1.1 配置Server代码编译规则

配置CMakeLists.txt编译规则:

  • 设置需要编译的代码和生成的可执行文件;
  • 设置链接库;

将以下代码复制进去:

add_executable(turtle_command_server src/turtle_command_server.cpp)
target_link_libraries(turtle_command_server ${catkin_LIBRARIES})

在这里插入图片描述

4.1.2 编译整个工作空间

cd ~/catkin_ws
catkin_make

4.1.3 配置环境变量

之前已经配置过。

4.1.4 执行代码

roscore
rosrun turtlesim turtlesim_node
rosrun learning_service turtle_command_server

可以看到服务端已经启动了,如下图所示:
在这里插入图片描述
接着我们再打开一个终端,输入以下命令使得小海龟动起来(可以通过tab键进行补全):

rosservice call /turtle_command "{}"

在这里插入图片描述
再输入一遍rosservice call /turtle_command "{}"这个命令,小海龟就会停下来了:
在这里插入图片描述

4.2 以Python为例

将代码turtle_command_server.py拷贝进新建立的scripts文件夹下(别忘了开启执行权限),完整代码为:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
########################################################################

# 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger

import rospy
import _thread,time
from geometry_msgs.msg import Twist
from std_srvs.srv import Trigger, TriggerResponse

pubCommand = False;
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)

def command_thread():	
	while True:
		if pubCommand:
			vel_msg = Twist()
			vel_msg.linear.x = 0.5
			vel_msg.angular.z = 0.2
			turtle_vel_pub.publish(vel_msg)
			
		time.sleep(0.1)

def commandCallback(req):
	global pubCommand
	pubCommand = bool(1-pubCommand)

	# 显示请求数据
	rospy.loginfo("Publish turtle velocity command![%d]", pubCommand)

	# 反馈数据
	return TriggerResponse(1, "Change turtle command state!")

def turtle_command_server():
	# ROS节点初始化
    rospy.init_node('turtle_command_server')

	# 创建一个名为/turtle_command的server,注册回调函数commandCallback
    s = rospy.Service('/turtle_command', Trigger, commandCallback)

	# 循环等待回调函数
    print("Ready to receive turtle command.")

    _thread.start_new_thread(command_thread, ())
    rospy.spin()

if __name__ == "__main__":
    turtle_command_server()

在回调函数中给Client端的反馈数据res是与Trigger相对应的,我们可以查看一下Trigger的数据结构。可以使用rossrv指令查看service中的数据类型:

rossrv show std_srvs/Trigger

在这里插入图片描述

4.2.1 配置Server代码编译规则

打开CMakeLists.txt文件,配置Python代码编译规则:

在这里插入图片描述

4.2.2 编译整个工作空间

cd ~/catkin_ws
catkin_make

4.2.3 配置环境变量

之前已经配置过。

4.2.4 执行代码

roscore
rosrun turtlesim turtlesim_node
rosrun learning_service turtle_command_server.py

可以看到服务端已经启动了,如下图所示:
在这里插入图片描述

接着我们再打开一个终端,输入以下命令使得小海龟动起来(可以通过tab键进行补全):

rosservice call /turtle_command "{}"

在这里插入图片描述

再输入一遍rosservice call /turtle_command "{}"这个命令,小海龟就会停下来了:
在这里插入图片描述

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

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

相关文章

12 张图看懂 CPU 缓存一致性与 MESI 协议,真的一致吗?

本文已收录到 GitHub AndroidFamily&#xff0c;有 Android 进阶知识体系&#xff0c;欢迎 Star。技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 进 Android 面试交流群。 前言 大家好&#xff0c;我是小彭。 在上一篇文章里&#xff0c;我们聊到了 CPU 的三级缓存结构…

测试工作3年还在基础岗?可能只是因为你的工作能力差

对于职场人而言&#xff0c;工作中升职加薪是每个人都梦寐以求的事情&#xff0c;但有些小伙伴表示&#xff0c;自己来到一个公司三年&#xff0c;却依旧停留在基础岗位上&#xff0c;究竟是什么原因呢&#xff1f; 其实从根本来说&#xff0c;很有可能只是因为&#xff1a;你…

Spring Boot日志配置及输出

1.日志框架有哪些&#xff1f; 常见的日志框架有log4j、logback、log4j2。 log4j这个日志框架显示是耳熟能详了&#xff0c;在Spring开发中是经常使用&#xff0c;但是据说log4j官方已经不再更新了&#xff0c;而且在性能上比logback、log4j2差了很多。 logback是由log4j创始…

WebRTC系列<四> 全面了解客户端-服务器网页游戏的WebRTC

转载&#xff1a;https://blog.brkho.com/2017/03/15/dive-into-client-server-web-games-webrtc/ 多人游戏很有趣。对于他们在单人沉浸感方面所缺乏的东西&#xff0c;在线游戏弥补了与朋友一起探索、在线结识陌生人以及与有能力的同龄人正面交锋的独特奖励体验。人们只需要看…

C# Control.DoubleBuffered 属性的使用

C# Control.DoubleBuffered 属性的使用 在我们开发的过程中,经常需要对界面进行美化,而美化的过程,一般来说就是添加图片, 让界面更加清新脱俗,更加耳目一新。 有一次有一个软件发送到客户那里试用,客户对功能是非常满意的,但是对界面的布局和颜色,就大为不满。 原来…

【Hack The Box】windows练习-- Resolute

HTB 学习笔记 【Hack The Box】windows练习-- Resolute &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年9月7日&#x1f334; &#x1…

uniapp picker 的使用,这玩意做的真不怎么样

uniapp picker 的使用&#xff0c;这玩意做的真不怎么样 最近要做小程序&#xff0c;考虑到需要多平台都用一套东西&#xff0c;就选用了 uniapp。 在写表单的时候用到它的 picker 组件&#xff0c;看官方文档楞是没看明白怎么用&#xff0c;试了半天没试出来&#xff0c;还是…

每日一题 —— LC. 790 多米诺和托米诺

有两种形状的瓷砖&#xff1a;一种是 2 x 1 的多米诺形&#xff0c;另一种是形如 “L” 的托米诺形。两种形状都可以旋转。 给定整数 n &#xff0c;返回可以平铺 2 x n 的面板的方法的数量。返回对 10^9 7 取模 的值。 平铺指的是每个正方形都必须有瓷砖覆盖。两个平铺不同&…

数据集成平台关于【源平台调度任务生命周期】

任务调度者 调度事件生产任务调度任务池-异步
AsynDispatcher --source 实例化适配器执行 消费任务实例化集成应用 DataHub Instance
handleSourceDispatch()依赖注入集成方案适配器调度条件检查执行适配器调度方法联动其它方案调度任务 SourceEvent 适配器调度周期 初始化…

化合物应用 | 动物实验溶剂选择

在给药时为了实现药物准确运送到动物体内、减少溶剂本身的副作用和毒性等的目标&#xff0c;需要选择合适的溶剂配方。溶剂的理化性质&#xff0c;如 pH、粘稠度、渗透压等都会对给药产生影响&#xff0c;需要慎重考虑。例如粘稠度过高可能会导致注射用针头的堵塞&#xff0c;粘…

作为新人,如何快速融入新团队?用好这8个点

大家好&#xff0c;之前在公司调岗&#xff0c;转到了新团队。 从一开始的不适应、不习惯&#xff0c;到现在的逐步习惯&#xff0c;真的就是和那句老话说的一样「有压力才会有成长」&#xff0c;下面晨光会结合在新团队学到的内容进行分享。 文章分为以下几个部分&#xff1…

通过云速搭CADT实现云原生分布式数据库PolarDB-X 2.0的部署

云速搭 CADT 是一款为上云应用提供自助式云架构管理的产品&#xff0c;显著地降低应用云上管理的难度和时间成本。本产品提供丰富的预制应用架构模板&#xff0c;同时也支持自助拖拽方式定义应用云上架构&#xff1b;支持较多阿里云服务的配置和管理。用户可以方便的对云上架构…

人力资源数字化转型,是企业高质量发展的关键

情景一 中层管理者&#xff0c;每天不是在开会&#xff0c;就是在帮下属解决问题&#xff0c;时间被搞的一团乱麻&#xff1b; 为了顺利推进项目&#xff0c;总是把自己逼成卷王&#xff0c;即使如此也没能挽救业绩下滑的命运。 情景二 由于业务能力出色被提拔带团队的新晋…

计算机网络-传输层(UDP协议报文格式,伪首部,UDP校验过程)

文章目录1. UDP协议UDP报文格式UDP校验过程1. UDP协议 UDP只在IP数据报服务之上增加了很少功能&#xff0c;即复用分用和差错检测功能。 UDP的主要特点: UDP是无连接的&#xff0c;减少开销和发送数据之前的时延。 UDP使用最大努力交付&#xff0c;即不保证可靠交付。 UDP是…

webpack5 Preload / Prefetch解决按需求加载速度

代码分离 | webpack 中文文档webpack 是一个模块打包器。它的主要目标是将 JavaScript 文件打包在一起&#xff0c;打包后的文件用于在浏览器中使用&#xff0c;但它也能够胜任转换&#xff08;transform&#xff09;、打包&#xff08;bundle&#xff09;或包裹&#xff08;pa…

vue_mixin混入

目录官网基本概念什么是Mixin混入和组件的区别混入和vuex的区别mixin的优点mixin的缺点使用mixin语法mixin局部混入-mixins全局混入-Vue.mixin方法(不推荐)mixin与组件合并逻辑[1]data数据总结举例说明[2]methods方法总结举例说明[3]生命周期函数总结举例说明问题&#xff1a;一…

Linux 进程信号

目录 一.信号 1.介绍 2.信号概念 3.查看系统定义的信号列表 4.信号处理的方式 二.信号产生前 1.用户层产生信号的方式 三.产生信号 1.通过按键产生信号 2.调用系统函数向进程发信号 &#xff08;1&#xff09;kill &#xff08;2&#xff09;raise &#xff08;…

大学生WEB前端静态网页——旅游介绍35页 响应式,

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 游景点介绍 | 旅游风景区 | 家乡介绍 | 等网站的设计与制作| HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&#xff1a;结构 CSS&…

Android 高通 Launcher3 添加桌面快捷方式

1、最近接到产测一个需求&#xff0c;需要在首页WorkSpace添加产测apk快捷方式&#xff0c;于是乎我去查看了一下Android12的源码&#xff0c;包名/build3/zm/Em_TK1080/EM_TK1080_prj/EM_TK1080_prj/qssi12/packages/apps/Launcher3/res/xml 主要修改文件 default_workspace…

TCP程序设计基础

TCP网络程序设计是指用Socket类编写通信程序。利用TCP协议进行通信的两个应用程序是有主次之分的&#xff0c;一个称为服务器程序&#xff0c;另一个称为客户机程序。两者的功能和编写方法不大一样。服务器端与客户端的交互过程如图所示&#xff1a; 1. InetAddress类 java.…