赞
踩
ROS2的Topic可以是一对一,一对多,多对一,多对多,同一个话题Topic可以被不同的节点Node订阅与发布
topic下有多种命令,以下是ros1的topic命令:
可以看到和ros2的topic没有什么区别
Commands: rostopic bw display bandwidth used by topic rostopic delay
display delay of topic from timestamp in header rostopic echo print
messages to screen rostopic find find topics by type rostopic hz
display publishing rate of topic rostopic info print information about
active topic rostopic list 获取话题列表 list active topics rostopic pub
发布话题数据 publish data to topic rostopic type print topic or field type
输出当前存在的话题Topic列表
ros2 topic list
OUTPUT:
/parameter_events
/rosout
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
当添加 -t 后缀时将同时输出话题列表与各个话题的消息类型Message Type
ros2 topic list -t
OUTPUT:
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
/turtle1/cmd_vel [geometry_msgs/msg/Twist]
/turtle1/color_sensor [turtlesim/msg/Color]
/turtle1/pose [turtlesim/msg/Pose]
如果要查看topic list中某个具体的的话题正在发布的内容,可以使用ros2 topic echo + 话题名
ros2 topic echo /turtle1/cmd_vel
OUTPUT: --- linear: x: 2.0 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.0 --- linear: x: 2.0 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.0 ---
pub可以在终端中直接发布命令,这在需要直接在命令行中简单输入即可调试时比较好用
ros2 topic pub <topic_name> <msg_type> '<args>'
单次发布
其中–once代表仅循环发布一次,然后退出,输入的结构内容是用yaml语法写的,因此在命令行中看起来比较繁杂。
ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
OUTPUT:
publisher: beginning loop
publishing #1: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=2.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=1.8))
循环发布
在pub后加入 --rate 1,代表循环频率为1HZ
ros2 topic pub --rate 1 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
OUTPUT:
publisher: beginning loop
publishing #1: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=2.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=1.8))
publishing #2: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=2.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=1.8))
publishing #3: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=2.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=1.8))
info可以显示话题Topic的类型与多少个节点Node正在发布它与订阅它
ros2 topic info /turtle1/cmd_vel
获取更详细的信息
ros2 topic info /turtle1/cmd_vel -v
# ros2 topic info /turtle1/cmd_vel -verbose
OUTPUT:
Type: geometry_msgs/msg/Twist
Publisher count: 1
Subscription count: 2
查看话题Topic的消息类型Message Type
ros2 topic type /turtle1/cmd_vel
OUTPUT:
geometry_msgs/msg/Twist
以下命令用的不多:
查看话题Topic发布的平均频率HZ
ros2 topic hz /turtle1/cmd_vel
OUTPUT:
average rate: 1.000
min: 1.000s max: 1.000s std dev: 0.00001s window: 2
average rate: 1.000
min: 0.999s max: 1.000s std dev: 0.00030s window: 4
average rate: 1.000
min: 0.999s max: 1.000s std dev: 0.00025s window: 6
average rate: 1.000
min: 0.999s max: 1.001s std dev: 0.00042s window: 7
查看话题所占用的带宽
ros2 topic bw /turtle1/cmd_vel
OUTPUT:
91 B/s from 3 messages
Message size mean: 52 B min: 52 B max: 52 B
153 B/s from 8 messages
Message size mean: 52 B min: 52 B max: 52 B
126 B/s from 9 messages
Message size mean: 52 B min: 52 B max: 52 B
198 B/s from 18 messages
Message size mean: 52 B min: 52 B max: 52 B
191 B/s from 21 messages
Message size mean: 52 B min: 52 B max: 52 B
186 B/s from 24 messages
Message size mean: 52 B min: 52 B max: 52 B
由消息类型Message Type 反查消息类型为该类型Type的话题Topic
ros2 topic find geometry_msgs/msg/Twist
OUTPUT:
/turtle1/cmd_vel
delay Display delay of topic from timestamp in header
当要查看具体消息类型Message Type的结构时,可以使用如下命令:
ros2 interface show geometry_msgs/msg/Twist
OUTPUT:
Vector3 linear
float64 x
float64 y
float64 z
Vector3 angular
float64 x
float64 y
float64 z
在ROS2中已经没有了Master的概念,避免master挂了,以提升系统的稳定性
ros2 pkg create --build-type ament_python py_pub_sub
在py_pub_sub功能包的py_pub_sub文件夹下新建源码文件publisher_member_function.py
touch publisher_member_function.py
ros2中提供的消息接口可以通过以下命令来查看
ros2 interface list
进而查看具体的消息类型的结构
ros2 interface show std_msgs/msg/String
OUTPUT:
# This was originally provided as an example message.
# It is deprecated as of Foxy
# It is recommended to create your own semantically meaningful message.
# However if you would like to continue using this please use the equivalent in example_msgs.
string data
编写步骤:
1.编程接口初始化
2.创建节点并初始化
3.创建发布者对象
4.创建话题并填充话题消息
5.发布话题消息
6.销毁节点并关闭接口
import rclpy # rclpy是ROS Client Library for Python的缩写,与Node有关的内容在这个库中 from rclpy.node import Node from std_msgs.msg import String # std_msgs是ROS内置的数据类型库,里面有msg、srv等一系列基础的数据类型 class MinimalPublisher(Node): # Node为这个类的父类 def __init__(self): super().__init__('minimal_publisher') # 调用父类中Node的构造函数,在此处直接为其赋名minimal_publisher # 创建publisher,数据类型为String,话题名为topic_name, 队列长度为10,它是QoS (quality of service) setting之一 self.example_publisher = self.create_publisher(String, 'topic_name', 10) # 创建发布者对象 timer_period = 0.5 # 定时器周期 in seconds self.timer = self.create_timer(timer_period, self.timer_callback) # 创建定时器 每个周期调用一次回调函数self.timer_callback self.i = 0 # 用于回调函数的一个计数器counter def timer_callback(self): # 定时器的回调函数 msg = String() # 定义消息类型为String类 msg.data = 'Hello World: %d' % self.i # 添加消息内容 self.example_publisher.publish(msg) # 发布消息 self.get_logger().info('Publishing: "%s"' % msg.data) # 可选的打印日志到控制台console self.i += 1 # 上面的部分为类内容 # 下面的部分是main函数 def main(args=None): # 主函数 rclpy.init(args=args) # 初始化 rclpy minimal_publisher = MinimalPublisher() # 定义MinimalPublisher类 rclpy.spin(minimal_publisher) # 循环 # Destroy the node explicitly # (optional - otherwise it will be done automatically # when the garbage collector destroys the node object) minimal_publisher.destroy_node() # 可以不写,会自动执行 rclpy.shutdown() #关闭 if __name__ == '__main__': # 该条下的所有代码仅当本脚本直接执行时会触发,如果在其他文件引用本文件,则不会触发以下的代码 main()
在功能包目录下打开package.xml,修改以下内容[可选,不影响使用]
例子:
<description>Examples of minimal publisher/subscriber using rclpy</description>
<maintainer email="hermanye233@icloud.com">Herman Ye</maintainer>
<license>Apache License 2.0</license>
继续添加内容[必须]
当功能包里的代码被执行时,这些语句声明了功能包的依赖
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
打开setup.py,添加入口点
maintainer='Herman Ye',
maintainer_email='hermanye233@icloud.com',
description='Examples of minimal publisher/subscriber using rclpy',
license='Apache License 2.0',
在entry_points下的这个位置添加以下命令
'talker = py_pub_sub.publisher_member_function:main',
最终效果:
entry_points={
'console_scripts': [
'talker = py_pub_sub.publisher_member_function:main',
],
},
setup.cfg是自动填写的,它将功能包的可执行文件放入lib中,ros2 run将会在lib中查找这些执行性文件是否存在并调用
[develop]
script_dir=$base/lib/py_pub_sub
[install]
install_scripts=$base/lib/py_pub_sub
在功能包src文件夹下新建源码文件pose_subscriber.cpp
touch pose_subscriber.cpp
1.编程接口初始化
2.创建节点并初始化
3.创建订阅者对象
4.通过回调函数处理话题数据
5.销毁节点、关闭接口
源码部分注释同publisher
import rclpy from rclpy.node import Node from std_msgs.msg import String class MinimalSubscriber(Node): def __init__(self): super().__init__('minimal_subscriber') # 订阅者的构造函数和回调函数不需要定时器Timer,因为当收到Message时,就已经启动回调函数了 # 注意此处不是subscriber,而是subscription # 数据类型,话题名,回调函数名,队列长度 self.subscription = self.create_subscription(String,'topic_name',self.listener_callback,10) self.subscription # prevent unused variable warning def listener_callback(self, msg): self.get_logger().info('I heard: "%s"' % msg.data) #回调函数内容为打印msg.data里的内容 def main(args=None): rclpy.init(args=args) minimal_subscriber = MinimalSubscriber() rclpy.spin(minimal_subscriber) # Destroy the node explicitly # (optional - otherwise it will be done automatically # when the garbage collector destroys the node object) minimal_subscriber.destroy_node() rclpy.shutdown() if __name__ == '__main__': main()
因为之前添加过了,所以不用再添加,如果subscriber有额外要使用的库,则需要添加新增的库
打开setup.py,添加入口点
在entry_points下的这个位置添加以下命令
'listener = py_pub_sub.subscriber_member_function:main',
最终效果:
entry_points={
'console_scripts': [
'talker = py_pub_sub.publisher_member_function:main',
'listener = py_pub_sub.subscriber_member_function:main',
],
},
ros2 run 在功能包中所能观测到的可执行文件的名字即此处设置的talker与listener
colcon build --packages-select py_pub_sub
ros2 run py_pub_sub listener
ros2 run py_pub_sub talker
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。