1. ROS2节点创建与生命周期管理
任务目标
创建一个ROS2 Python节点,该节点在启动时执行初始化操作,在运行期间周期性发布消息,在关闭时执行清理操作。通过该节点演示ROS2节点的标准生命周期:构造→初始化→执行→销毁,并观察节点状态转换。
环境依赖
- Ubuntu 22.04 + ROS2 Humble(或更高版本)
- 已安装
rclpy和std_msgs包 - 已source ROS2环境:
source /opt/ros/humble/setup.bash
完整实现
创建文件 lifecycle_node.py,内容如下:
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
import time
class LifecycleDemoNode(Node):
def __init__(self):
# 节点初始化:创建节点、声明参数、创建发布器
super().__init__('lifecycle_demo_node')
self.publisher = self.create_publisher(String, 'lifecycle_topic', 10)
self.timer = self.create_timer(1.0, self.timer_callback)
self.counter = 0
self.get_logger().info('节点已创建,进入初始化状态')
def timer_callback(self):
# 运行期间周期性执行
msg = String()
msg.data = f'第 {self.counter} 条消息'
self.publisher.publish(msg)
self.counter += 1
self.get_logger().info(f'发布: {msg.data}')
def destroy_node(self):
# 销毁前清理:停止定时器、记录日志
self.get_logger().info('节点销毁中,执行清理操作...')
self.timer.cancel()
super().destroy_node()
def main(args=None):
rclpy.init(args=args) # 1. 初始化ROS2客户端库
node = LifecycleDemoNode() # 2. 创建节点实例(构造+初始化)
try:
rclpy.spin(node) # 3. 进入执行循环,等待回调
except KeyboardInterrupt:
pass
finally:
node.destroy_node() # 4. 销毁节点(清理)
if rclpy.ok():
rclpy.shutdown() # 5. 关闭ROS2客户端库
print('节点已完全销毁,进程退出')
if __name__ == '__main__':
main()
运行方式
- 打开终端,source ROS2环境
- 运行节点:
python3 lifecycle_node.py - 另开终端,查看节点列表:
ros2 node list,应看到/lifecycle_demo_node - 查看话题消息:
ros2 topic echo /lifecycle_topic
验证方法与判定标准
- 初始化验证:运行节点后,终端输出
节点已创建,进入初始化状态,且ros2 node list能查到该节点 - 执行验证:每1秒输出一条
发布: 第 N 条消息,ros2 topic echo能收到对应消息 - 销毁验证:按
Ctrl+C终止进程,终端输出节点销毁中,执行清理操作...,随后进程正常退出,ros2 node list中节点消失 - 状态转换观察:运行
ros2 lifecycle get /lifecycle_demo_node可查看节点生命周期状态(当前为active),说明节点处于正常运行状态
生命周期状态说明
ROS2节点生命周期遵循标准状态机:未配置(unconfigured)→未激活(inactive)→激活(active)→最终化(finalized)。本案例中,节点创建后直接进入 active 状态(默认配置),通过 rclpy.spin() 保持执行,销毁时通过 destroy_node() 完成清理并退出。如需显式管理状态转换,可使用 rclpy.lifecycle 模块,但本案例聚焦于基础节点的创建与销毁流程。
常见问题
- 找不到
rclpy:确认已source ROS2环境,且Python版本匹配(ROS2 Humble需Python3.10) - 节点无法销毁:确保在
finally块中调用destroy_node(),避免异常导致资源泄漏 - 话题收不到消息:检查发布器队列长度(本案例设为10),并确认订阅方已启动