ROS Approximate Time Sync未进入回调函数问题排查求助
问题分析与解决办法
核心错误点
- 重复订阅+局部同步器失效:
onInit()中已订阅/cloud/cloud_out_merged,却又在segment回调里重复创建sub1_、sub2_订阅;且Synchronizer是局部变量,函数执行完毕后就会被销毁,根本无法持续监听并同步两个话题的消息。 - 订阅逻辑错位:订阅操作和同步器初始化必须在节点初始化阶段(
onInit())完成,而非每次收到点云消息才重复执行——重复订阅会创建大量无效订阅实例,直接干扰消息同步逻辑。
修正后的代码示例
// 类成员变量声明(需在头文件中添加) message_filters::Subscriber<sensor_msgs::PointCloud2> sub1_; message_filters::Subscriber<sensor_msgs::PointCloud2> sub2_; boost::shared_ptr<message_filters::Synchronizer<sync_policies::ApproximateTime<sensor_msgs::PointCloud2, sensor_msgs::PointCloud2>>> sync_; void OrganizedMultiPlaneSegmentation::onInit() { ros::NodeHandle& nh_ = getNodeHandle(); // 初始化阶段完成两个话题的订阅 sub1_.subscribe(nh_, "/cloud/cloud_out_merged", 5); sub2_.subscribe(nh_, "/cloud_out_normal", 5); // 同步器保存为类成员,避免局部销毁 typedef sync_policies::ApproximateTime<sensor_msgs::PointCloud2, sensor_msgs::PointCloud2> MySyncPolicy; sync_.reset(new Synchronizer<MySyncPolicy>(MySyncPolicy(40), sub1_, sub2_)); // sync_->setAgePenalty(1.0); // 按需启用该配置 sync_->registerCallback(boost::bind(&OrganizedMultiPlaneSegmentation::segmentPlanes, this, _1, _2)); } // 直接使用同步后的回调函数,原segment函数可删除 void OrganizedMultiPlaneSegmentation::segmentPlanes(const PointCloud2ConstPtr &cloud_msg1, const PointCloud2ConstPtr &cloud_msg2) { pcl::PointCloud<pointT>::Ptr cloud(new pcl::PointCloud<pointT>()); pcl::fromROSMsg(*cloud_msg1, *cloud); pcl::PointCloud<pcl::Normal>::Ptr normalCloud(new pcl::PointCloud<pcl::Normal>()); // 后续处理逻辑... }
额外排查方向
- 时间戳一致性:确认两个话题的消息时间戳差异是否在ApproximateTime的默认同步窗口(0.1秒)内,时间差过大会导致无法匹配。可通过
rosbag record录制话题,用rosbag info检查时间戳。 - 发布频率不匹配:若其中一个话题发布频率远低于另一个,可适当调大同步策略的队列大小(比如把40改为更大的值)。
- 订阅队列溢出:检查订阅队列大小(代码中设为5)是否足够,消息产生过快时可调大队列值避免丢失。
内容的提问来源于stack exchange,提问作者Pran-7
相关产品推荐
相关产品推荐

