ROS2 节点类中要避免While true 循环
在写ros2节点类中的成员函数时,有时候我们需要使用死循环如while true,但是这样会阻塞节点正常运行,如以下代码中如果不屏蔽while true 片段,那么节点将不会收到所订阅话题中的消息,也不会触发订阅回调函数,表现出明显的阻塞状态,但是将while true片段屏蔽后节点就可以正常运行,正确接收订阅话题中的消息,正确进入接收话题回调函数。
# 导入ros2的相关库
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
from std_msgs.msg import String# 导入公共库
import sys
import os
import time
import math
import numpy as np# 导入python串口库
import serial
import serial.tools.list_ports
print("import done")class uartHelper(Node):def __init__(self,name):super().__init__(name)# 创建订阅者并绑定接收回调函数self.sub = self.create_subscription(Twist,"/cmd_vel",self.sub_callback,1)print("List of enabled UART:")os.system('ls /dev/tty[a-ZA-Z]*')uart_dev = input("请输出需要测试的川口设备名称:") baudrate = input("请输入波特率(9600,19200,38400,57600,115200,921600):")try:self.ser = serial.Serial(uart_dev, int(baudrate), timeout=1) # 1s timeoutexcept Exception as e:print("open serial failed!\n")print("open seril success: ")print(self.ser)print("\n")#while True:# print("Running uart3 now! Press CTRL+C ot exit \n")# time.sleep(2)def sub_callback(self,msg_data):if not isinstance(msg_data,Twist): returnsend_data = "angular:"+str(msg_data.angular.z) + ";" + "linear:" + str(msg_data.linear.x)write_num = self.ser.wirte(send_data.encode('UTF-8'))print("Sending: ",send_data)def main(args=None):rclpy.init()uart_helper = uartHelper("uart_velctrl")rclpy.spin(uart_helper)uart_helper.destroy_node()rclpy.shutdown()
如果节点类程序中必须使用while true死循环函数,需在单独线程中开辟运行,避免阻塞ROS2的事件处理。
import rclpy
from rclpy.node import Node
import threadingclass MyNode(Node):def __init__(self):super().__init__('my_node')self.counter = 0# 启动单独线程运行循环threading.Thread(target=self.loop_thread, daemon=True).start()def loop_thread(self):"""在子线程中运行 while True 循环"""while True:self.get_logger().info(f"Thread Counter: {self.counter}")self.counter += 1self.sleep(1.0) # 必须使用 ROS2 的 sleep,避免阻塞def main(args=None):rclpy.init(args=args)node = MyNode()rclpy.spin(node)rclpy.shutdown()