一、创建功能包
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python pub_sub_example --dependencies rclpy std_msgs
cd ~/ros2_ws
colcon build
source install/setup.bash
二、实现发布者节点
# ~/ros2_ws/src/pub_sub_example/pub_sub_example/publisher_node.py
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
import time
class PublisherNode(Node):
def __init__(self):
super().__init__('publisher_node')
# 创建发布者,发布String类型消息到/topic话题,队列大小10
self.publisher_ = self.create_publisher(String, 'topic', 10)
timer_period = 1 # 发布间隔(秒)
self.timer = self.create_timer(timer_period, self.timer_callback)
self.i = 0
def timer_callback(self):
msg = String()
msg.data = f'Hello World: {self.i}'
self.publisher_.publish(msg)
self.get_logger().info(f'发布消息: "{msg.data}"')
self.i += 1
def main(args=None):
rclpy.init(args=args)
publisher = PublisherNode()
try:
rclpy.spin(publisher)
except KeyboardInterrupt:
pass
finally:
publisher.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
三、实现订阅者节点
# ~/ros2_ws/src/pub_sub_example/pub_sub_example/subscriber_node.py
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class SubscriberNode(Node):
def __init__(self):
super().__init__('subscriber_node')
# 创建订阅者,从/topic话题接收String类型消息,注册回调函数
self.subscription = self.create_subscription(
String,
'topic',
self.listener_callback,
10)
self.subscription # 防止未使用变量警告
def listener_callback(self, msg):
self.get_logger().info(f'接收到消息: "{msg.data}"')
def main(args=None):
rclpy.init(args=args)
subscriber = SubscriberNode()
try:
rclpy.spin(subscriber)
except KeyboardInterrupt:
pass
finally:
subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
四、配置 setup.py
# ~/ros2_ws/src/pub_sub_example/setup.py
entry_points={
'console_scripts': [
'publisher = pub_sub_example.publisher_node:main',
'subscriber = pub_sub_example.subscriber_node:main',
],
},
五、编译并运行
# 编译功能包
cd ~/ros2_ws
colcon build --packages-select pub_sub_example
source install/setup.bash
# 打开新终端1,运行发布者节点
ros2 run pub_sub_example publisher
# 打开新终端2,运行订阅者节点
ros2 run pub_sub_example subscriber
六、验证功能
[INFO] [1688888888.123456] [publisher_node]: 发布消息: "Hello World: 0"
[INFO] [1688888889.123456] [publisher_node]: 发布消息: "Hello World: 1"
...
[INFO] [1688888888.123456] [subscriber_node]: 接收到消息: "Hello World: 0"
[INFO] [1688888889.123456] [subscriber_node]: 接收到消息: "Hello World: 1"
...
七、关键知识点
发布者 (Publisher):
使用self.create_publisher()创建发布者
通过msg = String()创建标准消息
调用self.publisher_.publish(msg)发布消息
订阅者 (Subscriber):
使用self.create_subscription()创建订阅者
通过回调函数self.listener_callback处理接收到的消息
话题 (Topic):
发布者和订阅者通过相同的话题名称 (topic) 通信
话题类型必须匹配 (本例中均为std_msgs/String)
异步通信:
ROS2 采用异步通信模型,发布者和订阅者可以独立运行
消息通过 ROS2 的中间件 (DDS) 进行传输
八、扩展建议
修改发布频率:调整timer_period参数
使用自定义消息类型:创建并使用自己定义的 ROS2 消息
添加参数配置:使节点更加灵活
实现服务通信:尝试使用 ROS2 的服务 (Service) 机制
如果需要进一步优化或有特定功能需求,可以继续扩展这些节点的功能。