TurtleBot3 LDS-01传感器数据处理ROS节点报错求助:订阅/scan话题修改消息并发布至/scan_new时遇溢出与无消息接收问题
TurtleBot3 LDS-01 激光数据优化问题排查与解决
我来帮你一步步拆解这两个问题,都是激光雷达数据处理和ROS消息发布中常见的坑:
问题1:exp函数溢出警告与/scan_new话题值显示红色
核心原因
- 无效激光数据触发数值溢出:TurtleBot3的LDS-01在没检测到障碍物时,会返回
inf(无穷大)或者NaN值,这些值代入你的矩阵运算后,会让n1的数值变得极大,导致exp(-2*n1)计算时溢出——当n1是超大正数,-2*n1会变成极小的负数,exp会试图计算一个接近0的数,但数值范围超出了Python浮点数的处理能力,触发警告。 - 矩阵运算维度不匹配:你的
IW1_1是1×10的矩阵,但激光雷达的ranges有360个数据点,直接做矩阵乘法会导致维度错误,计算出的结果完全不符合预期,最终产生NaN/inf,终端里就会显示红色的无效值。
修复步骤
第一步:过滤无效激光数据
在转换x2之后,先把inf和NaN替换成传感器的最大量程(LDS-01是3.5m):
x2 = np.array(x1,dtype=float) # 替换所有无效值为3.5(LDS-01的最大检测距离) x2 = np.nan_to_num(x2, nan=3.5, posinf=3.5, neginf=3.5)
第二步:修正矩阵运算维度
你的神经网络是针对单个激光点设计的,所以要对360个点逐个处理,调整运算逻辑:
# 原来的layer1计算改成逐点处理 a1_list = [] for xp in xp1: # 单个点xp和1×10矩阵相乘,加上10×1的偏置b1 n1 = IW1_1 * xp + b1 # 限制n1的范围,避免exp溢出 n1 = np.clip(n1, -50, 50) a1 = 2/(1+np.exp(-2*n1)) - 1 a1_list.append(a1) # 转换成360×10的数组,方便后续运算 a1 = np.array(a1_list).reshape(-1, 10) # layer2计算调整为矩阵点积 a2 = np.dot(a1, LW2_1.T) + b2 # 转换成list格式,适配LaserScan的ranges字段 y2 = a2.flatten().tolist()
第三步:限制exp输入范围
给n1加个截断,避免数值过大导致溢出:
n1 = np.clip(n1, -50, 50)
问题2:订阅/scan_new时提示WARNING: no messages received and simulated time is active
核心原因
- LaserScan消息字段不完整:你只给
scan.ranges赋值了,但LaserScan消息需要header、angle_min、angle_max等必填字段,空的默认值会导致ROS无法正常解析消息,相当于没发布有效内容。 - 仿真时间配置错误:如果是在Gazebo仿真中运行,节点默认等待仿真时钟(
use_sim_time:=true),但如果Gazebo没启动或者/clock话题没发布,节点就会一直等待,订阅者收不到消息。
修复步骤
第一步:完整复制原消息的所有字段
不要用全局的空scan对象,而是基于订阅到的msg来修改,这样所有必要字段都会自动继承:
def callback(msg): # 完全复制原激光消息的所有字段(header、角度参数等) scan_new = LaserScan() scan_new = msg # 或者用深拷贝避免原消息被修改 # import copy # scan_new = copy.deepcopy(msg) x1 = msg.ranges x2 = np.array(x1,dtype=float) # ... 中间的过滤、计算步骤 ... # 把计算后的y2赋值给新消息的ranges scan_new.ranges = y2 pub.publish(scan_new)
第二步:检查仿真时间设置
- 真实机器人场景:运行节点时加上参数,禁用仿真时间:
rosrun your_package your_node.py __param:=use_sim_time:=false - Gazebo仿真场景:确保Gazebo已经启动,用
rostopic echo /clock检查是否有消息输出;如果是自己写的launch文件,要确保包含Gazebo的启动节点,并且设置use_sim_time:=true。
内容的提问来源于stack exchange,提问作者AmirulJ
相关产品推荐
相关产品推荐

