ROS Melodic下message_filters.ApproximateTimeSynchronizer无法触发回调问题
解决ROS Melodic中Ouster激光雷达与相机数据同步问题
一、先修复代码的基础错误
你的代码存在两个关键语法/逻辑问题,会直接导致回调无法触发:
- 回调函数无缩进:
callback函数定义后的代码块没有缩进,Python会识别为函数体为空,即使触发同步也不会执行任何操作。 - 节点初始化顺序错误:
rospy.init_node('sync_node')应该放在所有订阅器创建之前,ROS订阅器需要依赖已初始化的节点才能正常工作。
修复后的代码示例:
import rospy import message_filters from sensor_msgs.msg import Image, CameraInfo, PointCloud2 def callback(image_msg, camera_info_msg, lidar_msg): # Process synchronized data here rospy.loginfo("Received synchronized data!") # 可添加时间戳打印用于调试 rospy.loginfo(f"Image timestamp: {image_msg.header.stamp}") rospy.loginfo(f"Lidar timestamp: {lidar_msg.header.stamp}") if __name__ == "__main__": rospy.init_node('sync_node') # 初始化订阅器(必须在节点初始化之后) image_sub = message_filters.Subscriber('/cv_camera/image_raw', Image) info_sub = message_filters.Subscriber('/cv_camera/camera_info', CameraInfo) lidar_sub = message_filters.Subscriber('/ouster/points', PointCloud2) # 初始化近似时间同步器 ts = message_filters.ApproximateTimeSynchronizer( [image_sub, info_sub, lidar_sub], queue_size=10, slop=0.1 # 允许的时间差(秒),可根据实际情况调整 ) ts.registerCallback(callback) rospy.spin()
二、解决Ouster点云无时间戳的核心问题
ouster/points没有时间戳是同步失败的根本原因——ApproximateTimeSynchronizer完全依赖消息头中的stamp字段进行时间匹配,解决方法如下:
1. 配置Ouster ROS驱动生成时间戳
Ouster的ouster_ros驱动默认支持生成时间戳,需检查launch文件配置:
- 打开Ouster的启动launch文件(如
os1.launch),添加或确认以下参数:
<!-- 使用系统时间作为点云时间戳(无硬件同步时用) --> <param name="os1/use_system_time" value="true" /> <!-- 若有硬件同步(PPS/NMEA),启用以下参数 --> <param name="os1/use_pps" value="true" /> <param name="os1/use_nmea" value="true" />
重启驱动后,再次用rostopic echo /ouster/points/header/stamp验证时间戳是否生成。
2. 手动为点云补全时间戳(临时方案)
如果驱动无法自动生成时间戳,可创建一个中转节点为点云添加系统时间:
import rospy from sensor_msgs.msg import PointCloud2 def lidar_callback(msg): msg.header.stamp = rospy.Time.now() pub.publish(msg) if __name__ == "__main__": rospy.init_node('lidar_timestamp_adder') sub = rospy.Subscriber('/ouster/points', PointCloud2, lidar_callback) pub = rospy.Publisher('/ouster/points_with_stamp', PointCloud2, queue_size=10) rospy.spin()
之后在同步节点中订阅/ouster/points_with_stamp话题即可。
三、验证与调试
- 确认所有话题时间戳正常:
- 执行
rostopic echo /cv_camera/image_raw/header/stamp查看相机图像时间戳。 - 执行
rostopic echo /ouster/points/header/stamp确认激光雷达点云时间戳存在。
- 执行
- 调整同步时间差阈值:
若相机与激光雷达时间差较大,可增大ApproximateTimeSynchronizer的slop参数(如从0.1改为0.5秒),但不宜过大,避免匹配无关数据。 - 尝试严格时间同步(可选):
若通过硬件同步保证了相机与激光雷达时间严格对齐,可替换为严格时间同步器:ts = message_filters.TimeSynchronizer([image_sub, info_sub, lidar_sub], queue_size=10)
内容的提问来源于stack exchange,提问作者Rupika raj
相关产品推荐
相关产品推荐

