目录
四.参数设置
一、话题发布
需求:编码实现乌龟运动控制,让小乌龟做圆周运动
实现分析:
- 乌龟运动控制实现,关键节点有两个,一个是乌龟运动显示节点 turtlesim_node,另一个是控制节点,二者是订阅发布模式实现通信的,乌龟运动显示节点直接调用即可,运动控制节点之前是使用的 turtle_teleop_key通过键盘 控制,现在需要自定义控制节点(node 节点替换)。
- 控制节点自实现时,首先需要了解控制节点与显示节点通信使用的话题与消息,可以使用ros命令结合计算图来获取。
- 了解了话题与消息之后,通过 C++ 或 Python 编写运动控制节点,通过指定的话题,按照一定的逻辑发布消息即可。
实现流程:
- 通过计算图结合ros命令获取话题与消息信息。
- 编码实现运动控制节点。
- 启动 roscore、turtlesim_node 以及自定义的控制节点,查看运行结果
流程
1.话题与消息的获取
启动键盘控制乌龟
话题获取
rostopic list ##获取话题列表
rqt_graph
消息类型获取
rostopic info /turtle1/cmd_vel
rostopic type /turtle1/cmd_vel
消息格式获取
rosmsg show 消息类型
rosmsg info 消息类型
linear(线速度) 下的xyz分别对应在x、y和z方向上的速度(单位是 m/s);
angular(角速度)下的xyz分别对应x轴上的翻滚、y轴上俯仰和z轴上偏航的速度(单位是rad/s)。
2.实现发布节点(python)
新建功能包-->python文件
#! /usr/bin/env python
# coding=UTF-8
# 1.导包
import rospy
from geometry_msgs.msg import Twist
"""
发布方:发布速度消息
话题名:/turtle1/cmd_vel
消息格式:geometry_msgs/Twist
步骤:
1、导包
2、初始化ros节点
3、创建发布者对象
4、组织数据并发布数据
"""
if __name__=="__main__":
# 2.# 初始化ros节点
rospy.init_node("my_control")
# 3.创建发布者对象
pub=rospy.Publisher("/turtle1/cmd_vel",Twist,queue_size=10) #话题 ,消息类型,数据长度
# 4.诅咒你数据并发布数据
# 4.1设置发布频率
rate=rospy.Rate(10)
# 4.2创建发布消息
chl=Twist()
# 线速度
chl.linear.x=0.5
chl.linear.y=0.0
chl.linear.z=0.0
# 角速度
chl.angular.x=0.0
chl.angular.y=0.0
chl.angular.z=0.5
# 4.3循环实现
while not rospy.is_shutdown(): #判断rospy是否被关闭
pub.publish(chl) #f发布者对象pub发布消息chl
rate.sleep
执行权限-->编译-->roscore -->启动乌龟GUI--> 启动发布方(rosrun plumbing_test pub_twist.py )
二、话题订阅
需求描述:已知turtlesim中的乌龟显示节点(乌龟GUI),会发布当前乌龟的位姿(窗体中乌龟的坐标以及朝向),要求控制乌龟运动,并时时打印当前乌龟的位姿
实现分析:
- 首先,需要启动乌龟显示以及运动控制节点并控制乌龟运动。
- 要通过ROS命令,来获取乌龟位姿发布的话题以及消息。
- 编写订阅节点,订阅并打印乌龟的位姿。
实现流程:
- 通过ros命令获取话题与消息信息。
- 编码实现位姿获取节点。
- 启动 roscore、turtlesim_node 、控制节点以及位姿订阅节点,控制乌龟运动并输出乌龟的位姿。
1.话题和消息的获取 (和前面话题发布一致)
新建launch文件,进行集成
<!-- 启动乌龟Gui与键盘控制节点 -->
<launch>
<!-- 乌龟GUI 功能包 运行的节点文件 自定义名字 输出到屏幕上-->
<node pkg="turtlesim" type="turtlesim_node" name="turtle1" output="screen"/>
<!-- 键盘控制 -->
<node pkg="turtlesim" type="turtle_teleop_key" name="key" output="screen"/>
</launch>
编译 --> roscore -->source -->运行 (roslaunch)
话题名称获取
消息类型获取
消息格式获取
2.实现订阅节点
创建python文件
代码:
#! /usr/bin/env python
# coding=UTF-8
"""
需求: 订阅并输出乌龟位姿信息
实现流程:
1.导包
2.初始化 ROS 节点:命名(唯一)
3创建 订阅者 对象
4.处理订阅的消息(回调函数)
5.设置循环调用回调函数 Spin()
"""
#1.导包
import rospy
from turtlesim.msg import Pose #消息格式是turtlesim/Pose 导包从turtlesim.msg(话题通信的消息包)下的Pose
def doPose(pose):
rospy.loginfo("p--->乌龟位姿信息:坐标(%.2f,%.2f),朝向:%.2f,线速度:%.2f,角速度:%.2f",
pose.x, pose.y, pose.theta, pose.linear_velocity, pose.angular_velocity)
if __name__ == "__main__":
#2.初始化 ROS 节点:命名(唯一)
rospy.init_node("sub_pose")
#3.创建 订阅者 对象
sub = rospy.Subscriber("/turtle1/pose",Pose,doPose,queue_size=100) #话题名字要和发布者一致
#4.处理订阅的消息(回调函数)
#5.设置循环调用回调函数
rospy.spin()
执行
启动乌龟GUI(launch文件启动) --> 编译执行订阅方python文件
三.服务调用
需求描述:编码实现向 turtlesim 发送请求,在乌龟显示节点的窗体指定位置生成一乌龟,这是一个服务请求 操作。
实现分析:
- 首先,需要启动乌龟显示节点。
- 要通过ROS命令,来获取乌龟生成服务的服务名称以及服务消息类型。
- 编写服务请求节点,生成新的乌龟。
实现流程:
- 通过ros命令获取服务与服务消息信息。
- 编码实现服务请求节点。
- 启动 roscore、turtlesim_node 、乌龟生成节点,生成新的乌龟。
1. 服务名称以及服务消息获取
话题: (使用的是/spawn)
rosservice list
获取消息类型:turtlesim/Spawn
rosservice type /spawn
rosservice info /spawn
获取消息格式:
rossrv info turtlesim/Spawn
2.服务客户端实现
命令实现 /sapwn 后面的内容用Tab自动补齐
新建python文件
#! /usr/bin/env python
# coding=UTF-8
# 1.导包
import rospy
from turtlesim.srv import Spawn,SpawnRequest,SpawnResponse # 消息类型:turtlesim/Spawn
"""
需求:向服务器发送请求生产一只小乌龟
话题:/spawn
消息类型:turtlesim/Spawn
1、导包
2、初始化ros节点
3、创建服务的客户端对象
4、组织数据并发送请求
5、处理响应结果
"""
if __name__=="__main__":
# 2.初始化ROS节点
rospy.init_node("service_call")
# 3、创建服务的客户端对象
client = rospy.ServiceProxy("/spawn", Spawn) # 话题 消息类型
#4. 组织数据并发送请求
request = SpawnRequest()
request.x = 4.5 #行坐标
request.y = 2.0 #纵坐标
request.theta = -3 #转向角度
request.name = "turtle3" #名字
client.wait_for_service() # 服务器没有启动时挂起
try:
response = client.call(request)
# 5. # 响应结果
rospy.loginfo("生成乌龟的名字叫:%s", response.name)
except Exception as e:
rospy.loginfo("请求处理异常")
运行
四.参数设置
需求描述:修改turtlesim乌龟显示节点窗体的背景色,已知背景色是通过参数服务器的方式以 rgb 方式设置的。
实现分析:
- 首先,需要启动乌龟显示节点
- 要通过ROS命令,来获取参数服务器中设置背景色的参数
- 编写参数设置节点,修改参数服务器中的参数值
实现流程:
- 通过ros命令获取参数
- 编码实现服参数设置节点
- 启动 roscore、turtlesim_node 与参数设置节点,查看运行结果
1. 参数名获取
获取参数列表:
rosparam list
终端实现
获取参数值
rosparam get 参数名
更该参数
rosparam set /background_r 255
新建python文件
#! /usr/bin/env python
# coding=UTF-8
import rospy
"""
需求:修改乌龟GUI的背景色
1、初始化ros节点
2、设置参数
"""
if __name__=="__main__":
rospy.init_node("change_bgColor")
rospy.set_param("/turtlesim/background_r", 60)
rospy.set_param("/turtlesim/background_g", 70)
rospy.set_param("/turtlesim/background_b", 80)
5.
三种通信机制中,参数服务器是一种数据共享机制,可以在不同的节点之间共享数据,话题通信与服务通信是在不同的节点之间传递数据的,三者是ROS中最基础也是应用最为广泛的通信机制。
这其中,话题通信和服务通信有一定的相似性也有本质上的差异,在此将二者做一下简单比较:
二者的实现流程是比较相似的,都是涉及到四个要素:
- 要素1: 消息的发布方/客户端(Publisher/Client)
- 要素2: 消息的订阅方/服务端(Subscriber/Server)
- 要素3: 话题名称(Topic/Service)
- 要素4: 数据载体(msg/srv)
可以概括为: 两个节点通过话题关联到一起,并使用某种类型的数据载体实现数据传输。
二者的实现也是有本质差异的,具体比较如下:
Topic(话题) | Service(服务) | |
---|---|---|
通信模式 | 发布/订阅 | 请求/响应 |
同步性 | 异步 | 同步 |
底层协议 | ROSTCP/ROSUDP | ROSTCP/ROSUDP |
缓冲区 | 有 | 无 |
时时性 | 弱 | 强 |
节点关系 | 多对多 | 一对多(一个 Server) |
通信数据 | msg | srv |
使用场景 | 连续高频的数据发布与接收:雷达、里程计 | 偶尔调用或执行某一项特定功能:拍照、语音识别 |
不同通信机制有一定的互补性,都有各自适应的应用场景。尤其是话题与服务通信,需要结合具体的应用场景与二者的差异,选择合适的通信机制。