ROS服务Service通信机制在无人车中的具体应用

news2024/10/1 1:29:43

1、引言

我们在通信机制中,前面已有介绍这个Service服务:ROS通信机制之服务(Service)的应用
一般在一些通信处理比较简单的场景比较适合,这里我们在无人车上面来实际操作一些很常见的服务:发布电压数据、点亮与关闭LED灯、开启与关闭蜂鸣器、以及控制左右马达的速度等操作。

服务端:提供服务的节点,定义了一个回调函数,用来处理请求
客户端:服务请求的节点,通过本地代理去调用这个服务

工作区与包的创建过程就忽略了,有兴趣的可以查阅:ROS新建工作区(workspace)与包(package)编译的实践(C++示例)

2、无人车应用

2.1、目录

先来了解下有哪些消息、服务、节点文件:

cd ~/workspace/catkin_ws/src
ls jetbotmini_msgs/msg
ls jetbotmini_msgs/srv
ls jetbot_ros/scripts

截图如下:

2.2、启动节点

然后我们直接开启ROSMASTER之后,启动无人车的节点,后续将主要代码贴出,更加清晰了解无人车的服务通信机制。

roscore
rosrun jetbot_ros jetbotmini_driver.py

好的,现在我们就可以对无人车进行通信了

2.3、查看话题

先来看下有哪些话题:rostopic list

/rosout
/rosout_agg
/voltage

这里可以看到,有了一个 voltage 电压的话题。 


2.4、查看服务

接着重点来看下提供了哪些服务列表:rosservice list

/Buzzer
/LEDBLUE
/LEDGREE
/Motor
/Servo
/driver_node/get_loggers
/driver_node/set_logger_level
/rosout/get_loggers
/rosout/set_logger_level 

服务列表中有蜂鸣器,LED灯、马达、舵机等服务,接下来我们通过命令行来操作这些服务,让其和无人车进行通信。
服务的定义很简单,我们来具体查看下

2.5、蜂鸣器

输入命令:rossrv show Buzzer

输入类型跟输出类型之间使用三根小横短线隔开--- 

[jetbotmini_msgs/Buzzer]:
int32 buzzer
---
bool result

开启蜂鸣器:rosservice call /Buzzer "buzzer: 1"
result: True    #这个是返回值
关闭蜂鸣器:rosservice call /Buzzer "buzzer: 0"
result: True 

2.6、舵机

输入命令:rossrv show Servo 

[jetbotmini_msgs/Servo]:
int32 servoid
int32 angle
---
bool result

我的无人车有两个舵机接口S1和S2,如下图:

舵机1角度90:rosservice call /Servo 1 90
result: True
舵机2角度90:rosservice call /Servo 2 90
result: True 

查看舵机参数:rosservice args Servo
servoid angle

舵机1旋转30度角:rosservice call /Servo 1 30

当然参数是多个的时候,也可以指定参数名称的写法,使用字典形式来执行,这样更直观:
rosservice call /Servo "{'servoid': 1, 'angle': 30}" 

2.7、LED灯

点亮LEB蓝灯:rosservice call /LEDBLUE 1
result: True
如下图:

点亮LED绿灯:rosservice call /LEDGREE 1
result: True
如下图: 

一起点亮: 

2.8、电机(马达) 

查看Motor马达的数据类型结构:rossrv show Motor

[jetbotmini_msgs/Motor]:
float32 rightspeed
float32 leftspeed
---
bool result 

查看Motor马达的参数:rosservice args Motor

rightspeed leftspeed

【rightspeed】 :[-1, 1],右边电机速度,小于0反转,大于0正转。
【leftspeed】:[-1, 1],左边电机速度,小于0反转,大于0正转。

左电机(马达轮子)50%速度,右马达80%速度:rosservice call /Motor 0.5 0.8 

查看有哪些话题:rostopic list 

/rosout
/rosout_agg
/voltage 

可视化查看话题消息:rosrun rqt_topic rqt_topic
如下图,点击voltage话题的复选框进行勾选: 

这样就可以直观的看到电压是10.67V,频率是0.03赫兹(每30秒更新一次) 

3、jetbotmini_driver.py

重点来看下这个节点的代码,里面就是上述定义的各种服务,所以我们将消息和服务给导入进来:

from jetbotmini_msgs.msg import *
from jetbotmini_msgs.srv import *

jetbotmini_msgs.msgjetbotmini_msgs.srv是自动生成的,关于消息的定义在前面也有介绍,有兴趣的可以查阅:ROS通信机制之话题(Topics)的发布与订阅以及自定义消息的实现
会根据你的Python版本生成到对应位置,比如我这里是在下面这个目录
~/workspace/catkin_ws/devel/lib/python2.7/dist-packages/jetbotmini_msgs
分别生成在这里面的msgsrv文件夹里面。
截图如下:


接着回到jetbotmini_driver.py这个文件,源码如下: 

#!/usr/bin/env python3
# encoding: utf-8
import rospy
import random
import threading
from time import sleep
from jetbotmini_msgs.msg import *
from jetbotmini_msgs.srv import *
import RPi.GPIO as GPIO # Raspberry Pi 的GPIO库
import smbus

bus = smbus.SMBus(1) # 使用编号为1的总线,用于I2C通信
ADDRESS = 0x1B
Led_G_pin = 24 # 引脚编号
Led_B_pin = 23
Key1_pin = 8
GPIO.setmode(GPIO.BCM) # BCM模式是指使用Broadcom SOC通道编号的方式
GPIO.setup(Led_G_pin, GPIO.OUT, initial=GPIO.HIGH) # 引脚设置为输出模式,初始化为高电平
GPIO.setup(Led_B_pin, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(Key1_pin, GPIO.IN) #输入模式,可以读取引脚的状态

print("Starting now!")

class transbot_driver:
    def __init__(self):
        rospy.on_shutdown(self.cancel)
        self.srv_Buzzer = rospy.Service("/Buzzer", Buzzer, self.Buzzercallback)
        self.srv_Servo = rospy.Service("/Servo", Servo, self.Servocallback)
        self.srv_LEDBLUE = rospy.Service("/LEDBLUE", LEDBLUE, self.LEDBLUEcallback)
        self.srv_LEDGREE = rospy.Service("/LEDGREE", LEDGREE, self.LEDGREEcallback)
        self.srv_Motor = rospy.Service("/Motor", Motor, self.Motorcallback)
        self.volPublisher = rospy.Publisher("/voltage", Battery, queue_size=10)

    def cancel(self):
        self.srv_Buzzer.shutdown()
        self.srv_Servo.shutdown()
        self.srv_LEDBLUE.shutdown()
        self.srv_LEDGREE.shutdown()
        self.srv_Motor.shutdown()
        self.volPublisher.unregister()
        GPIO.cleanup()
        rospy.loginfo("Close the robot...")
        rospy.sleep(1)

    def pub_data(self):
        # 发布电池电压
        while not rospy.is_shutdown():
            sleep(30)
            AD_value = bus.read_i2c_block_data(ADDRESS,0x00,2)
            voltage = ((AD_value[0] << 8) + AD_value[1]) * 13.3 / 1023.0
            battery = Battery()
            battery.Voltage = voltage
            self.volPublisher.publish(battery)

    def Buzzercallback(self, request):
        #蜂鸣器控制,服务器回调函数
        if not isinstance(request, BuzzerRequest): return
        bus.write_byte_data(ADDRESS,0x06,request.buzzer)
        sleep(0.01)
        bus.write_byte_data(ADDRESS,0x06,request.buzzer)
        response = BuzzerResponse()
        response.result = True
        return response

    def Servocallback(self, request):
        # 控制舵机
        if not isinstance(request, ServoRequest): return
        bus.write_i2c_block_data(ADDRESS,3,[request.servoid,request.angle])
        sleep(0.01)
        bus.write_i2c_block_data(ADDRESS,3,[request.servoid,request.angle])
        response = ServoResponse()
        response.result = True
        return response

    def LEDBLUEcallback(self, request):
        # 控制蓝色LED
        if not isinstance(request, LEDBLUERequest): return
        if request.ledblue == 1:
            GPIO.output(Led_B_pin, GPIO.LOW)
        elif request.ledblue == 0:
            GPIO.output(Led_B_pin, GPIO.HIGH)
        response = LEDBLUEResponse()
        response.result = True
        return response

    def LEDGREEcallback(self, request):
        # 控制绿色LED
        if not isinstance(request, LEDGREERequest): return
        if request.ledgree == 1:
            GPIO.output(Led_G_pin, GPIO.LOW)
        elif request.ledgree == 0:
            GPIO.output(Led_G_pin, GPIO.HIGH)
        response = LEDGREEResponse()
        response.result = True
        return response

    def Motorcallback(self, request):
        # 控制马达,速度小于0就反方向
        if not isinstance(request, MotorRequest): return
        if request.leftspeed < 0:
            request.leftspeed = -request.leftspeed
            leftdir = 0
        else:
            leftdir = 1
        if request.rightspeed < 0:
            request.rightspeed = -request.rightspeed
            rightdir = 0
        else:
            rightdir = 1
        bus.write_i2c_block_data(ADDRESS,0x01,[leftdir,int(request.leftspeed*255),rightdir,int(request.rightspeed*255)])
        sleep(0.01)
        bus.write_i2c_block_data(ADDRESS,0x01,[leftdir,int(request.leftspeed*255),rightdir,int(request.rightspeed*255)])
        response = MotorResponse()
        response.result = True
        return response

if __name__ == '__main__':
    rospy.init_node("driver_node", anonymous=False)
    try:
        driver = transbot_driver()
        driver.pub_data()
        rospy.spin()
    except:
        rospy.loginfo("Final!!!")

首先初始化一些相关操作,将GPIO设置成BCM模式,然后根据引脚编号来初始化成高电平,模式是输出模式,这样就可以根据高低电平来控制LED灯,如果想要控制亮度,就需要使用到PWM脉宽调制方法。需要注意的是,cancel函数里面的GPIO.cleanup(),让引脚恢复到原来的状态,释放所有引脚不再有输出,避免一些电气的损坏与火灾的发生。
其余的都是一些回调函数,主要是一些写入和判断操作,通过这些回调函数就可以操作对应的元器件了。

这节主要是对Service服务做一个实操,巩固其作为通信机制之一的用法,在实际当中的具体运用。
其中代码里面有一些关于GPIO通用输入输出的知识点,有兴趣的可以查阅:
JetsonNano板子的RPi.GPIO接口实物图和功能介绍

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

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

相关文章

关于变电站综合自动化系统的案例应用分析-安科瑞 蒋静

摘 要&#xff1a;变电站综合自动化系统是将变电站内的二次设备经过功能的组合和优化设计&#xff0c;利用先进的计算机技术、通信技术、信号处理技术&#xff0c;实现对全变电站的主要设备和输、配电线路的自动监视、测量、控制、保护、并与上级调度通信的综合性自动化功能。 …

【Linux】编译安装nginx,手写service配置文件,深度理解systemd控制管理服务底层原理

目录 一、了解服务 1、服务的本质 2、centos7的systemd的服务 3、service unit file配置文件的组成以及掌握常用选项 4、关于systemd管理的命令学习 5、运行级别 二、编译安装nginx&#xff0c;以及手写service配置文件&#xff0c;请看注释 ​编辑 一、了解服务 1、服…

AI+BI行业数字化转型研讨会 - 总结精华回顾

带您一起观看研讨会精彩内容回顾&#xff01; || 导语 AIBI行业数字化转型研讨会—引领未来&#xff0c;智慧转型 德昂信息技术(北京)有限公司于2023年10月26日成功举办了AIBI行业数字化转型研讨会。此次盛会汇聚了产业精英、企业领袖以及技术专家&#xff0c;共同探讨在快速…

白盒测试用例的设计(图文讲解,超详细)

正文 语句覆盖&#xff1a;每条语句至少执行一次。判定覆盖&#xff1a;每个判定的所有可能结果至少出现一次。&#xff08;又称“分支覆盖”&#xff09;条件覆盖&#xff1a;每个条件的所有可能结果至少执行一次。判定/条件覆盖&#xff1a;一个判定中的每个条件的所有可能结…

多行业万能预约门店小程序源码系统 轻松预约 避免排队 带完整搭建教程

大家好啊&#xff0c;今天源码小编来给大家分享一款超级好用的多行业万能预约门店小程序源码系统。随着人们的生活节奏越来越快&#xff0c;对方便、快捷的服务需求越来越高。在消费升级的大背景下&#xff0c;多行业万能预约门店小程序源码系统的开发应运而生&#xff0c;旨在…

使用内网穿透工具,远程测试本地接口

学习目标&#xff1a; 目标 含义&#xff1a; 内网穿透工具是一种能够帮助没有公网IP或者动态IP用户进行远程访问内网应用的工具。通过内网穿透&#xff0c;用户无论身处任何网络环境&#xff0c;都可以方便地访问企业内部的ERP、OA、CRM等应用。内网穿透工具还支持默认的Htt…

XCC批量更新固件微码

适用&#xff1a; XCC Web界面微码批量更新&#xff0c;通过NFS或CIFS存储库更新所有适用于此服务器的固件微码&#xff0c;实现减少操作步骤&#xff0c;缩短时间周期。 更新事项 更新所有符合XCC更新规则的固件微码&#xff0c;包括UEFI、XCC、LXPM、网卡、RAID卡、RAID H…

【广州华锐互动】影视制作VR在线学习:身临其境,提高学习效率

随着科技的不断发展&#xff0c;影视后期制作技术也在日新月异。然而&#xff0c;传统的教学方式往往难以满足学员的学习需求&#xff0c;无法充分展现影视后期制作的魅力和潜力。近年来&#xff0c;虚拟现实(VR)技术的崛起为教学领域带来了新的机遇。通过VR教学课件&#xff0…

iOS代码混淆----自动

​ 先大致解释一下“编译"、"反编译": 编译&#xff1a;就是把千千万万行字符串(也叫代码&#xff0c;或者源文件)&#xff0c;变成010101010101(机器码&#xff0c;也叫目标代码) 编译过程&#xff1a;预处理-编译-汇编-链接 我的脚本运行在预处理阶段。 反…

技术干货 | GreatDB新一代读写分离架构,如何炼就近乎0损耗的性能?

优化数据库性能并降低成本是每位架构师和DBA都必须面对的挑战。其中&#xff0c;读写分离是一种常见方法&#xff1a;即通过将读操作和写操作分发到不同的数据库实例&#xff0c;实现多副本负载和性能提升。 传统的中间件方案&#xff0c;例如基于Proxysql、HAProxy、MySQL Ro…

社科赛斯预测考研趋势,竞争白热化后,稳上岸还是冲名校?

对于考研党来说&#xff0c;择校应该是备考过程中最纠结的一件事情了。这几年来影响院校选择的情况愈加复杂多变&#xff0c;单一志愿的限制下&#xff0c;如何预测报名走向&#xff0c;如何选择院校才能够成功上岸&#xff0c;不像是一个人的战斗&#xff0c;更像是一场几百万…

机器学习基础之《回归与聚类算法(5)—分类的评估方法》

问题&#xff1a;上一篇的案例&#xff0c;真的患癌症的&#xff0c;能被检查出来的概率&#xff1f; 一、精确率和召回率 1、混淆矩阵 在分类任务下&#xff0c;预测结果(Predicted Condition)与正确标记(True Condition)之间存在四种不同的组合&#xff0c;构成混淆矩阵(适…

法大大助力“民营旅行社第一股”数字化创新!

根据中国文旅部统计数据显示&#xff0c;2010-2019年&#xff0c;国内旅游市场持续平稳增长&#xff0c;2019年国内旅游人数突破60亿人次&#xff0c;而进入2020年&#xff0c;疫情的暴发使得全球旅游业遭受大创&#xff0c;国内旅游人次也跌至28.79亿人次。如今伴随着政策及环…

美元持续下跌,亚洲新兴市场货币有望脱颖而出?

KlipC报道&#xff1a;在过去几个月&#xff0c;美元大跌成了外汇市场最显眼的主题&#xff0c;追踪美元兑其他十种货币汇率的彭博美元现货指数上周也重挫了近1.5%&#xff0c;创下7月以来最大的周跌幅。 周一&#xff08;11月6日&#xff09;&#xff0c;由于美联储减弱强硬言…

电路设计中的 “热地” 和 “冷地”

一次跳闸事故引起的对 “热地” 的认识 ...... by 矜辰所致前言 最近做了一个简单的小设备&#xff0c;从某宝采购的便宜的成品带外壳&#xff0c;自己改造一下换成带无线通讯的产品&#xff0c;使用过程中忽略了阻容降压只有 “ 热地 ” 的问题&#xff0c;整得跳闸了好几次…

大数据之LibrA数据库系统告警处理(ALM-12030 无合法license存在)

告警解释 系统在安装集群后和每天零点检查当前系统中是否存在合法的license文件&#xff0c;如果没有则产生该告警。 导入合法license文件时&#xff0c;告警恢复。 说明&#xff1a; 如果当前集群使用节点数小于等于10节点&#xff08;不包含管理节点&#xff09;&#xf…

RHCE 9.0培训课程之容器技术的运行

红帽RHCE9.0学什么内容&#xff0c;新版有什么变化-CSDN博客文章浏览阅读102次。红帽是首个&#xff08;也是全球最大、全球领先&#xff09;的企业开源软件解决方案提供商&#xff0c;在过去 20 几年里&#xff0c;红帽已经成为开源社区里令人尊敬的成员&#xff0c;赞助了数百…

k8s-----数据存储

目录 一、数据存储的概念 二、基本存储 1、EmptyDir存储卷 2、hostPath存储卷 3、nfs共享存储卷 三、高级存储 1、PV&#xff08;持久化卷&#xff09; 2、PVC&#xff08;持久化卷声明&#xff09; 3、静态PV实验 4、动态PV实验 4.1 在stor01节点上安装nfs&#xf…

(Git)git clone报错——SSL certificate problem: self signed certificate

(Git)git clone报错——SSL certificate problem: self signed certificate 克隆代码时报错 问题分析 提示信息为SSL认证失败&#xff0c;可以关闭SSL的认证。 公司bitbucket只支持https地址&#xff0c;需要client配置忽略https证书检验。 解决方法 在克隆前输入下边命令&…

G-LAB IT实验室【11月】网工公开课 即将开始~

带你一起走进网工的世界&#xff01;G-LAB网工入门免费公开课即将开讲&#xff01;无论是想学习基础网络组网还是网络互通技术实施&#xff0c;这个公开课都是你不容错过的&#xff01; 公开课课程为期两天&#xff0c;11月7日&#xff06;11月8日晚20&#xff1a;00 分享主题…