鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    ApproximateTime 同步不成功

    已定时 已固定 已锁定 已移动 未解决
    综合问题
    时间同步 时间戳 approximatetime
    1
    1
    116
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 秋
      秋露凝雪
      最后由 编辑

      我的系统是ubuntu20.04,用的ros是galactic,我在同步之前录制了一个bag包,包含6个相机和一个激光雷达的信息系,下面是bag包的相关信息:

      c606@ubuntu:~/fyx/data_bag$ ros2 bag info rosbag2_2025_07_10-03_25_26
      
      Files:             rosbag2_2025_07_10-03_25_26_0.db3
      Bag size:          2.4 GiB
      Storage id:        sqlite3
      Duration:          17.252s
      Start:             Jul 10 2025 03:25:28.197 (1752143128.197)
      End:               Jul 10 2025 03:25:45.450 (1752143145.450)
      Messages:          999
      Topic information: Topic: /rslidar_points | Type: sensor_msgs/msg/PointCloud2 | Count: 173 | Serialization Format: cdr
                         Topic: /camera1/pylon_ros2_camera_node/image_raw | Type: sensor_msgs/msg/Image | Count: 135 | Serialization Format: cdr
                         Topic: /camera3/pylon_ros2_camera_node/image_raw | Type: sensor_msgs/msg/Image | Count: 137 | Serialization Format: cdr
                         Topic: /camera2/pylon_ros2_camera_node/image_raw | Type: sensor_msgs/msg/Image | Count: 123 | Serialization Format: cdr
                         Topic: /camera4/pylon_ros2_camera_node/image_raw | Type: sensor_msgs/msg/Image | Count: 144 | Serialization Format: cdr
                         Topic: /camera5/pylon_ros2_camera_node/image_raw | Type: sensor_msgs/msg/Image | Count: 146 | Serialization Format: cdr
                         Topic: /camera6/pylon_ros2_camera_node/image_raw | Type: sensor_msgs/msg/Image | Count: 141 | Serialization Format: cdr
      

      接着我写了一个功能包,作用是接受相机和雷达的话题,将话题内容同步后再以话题的形式发送出去,在写好节点代码后,我先通过命令ros2 run sys_time sys_time_node开启节点,再通过ros2 bag record -o synced_bag /clock $(ros2 topic list | grep "synced")命令开启录制,最后通过ros2 bag play rosbag2_2025_07_10-03_25_26 --loop --clock --read-ahead-queue-size 10000命令播放原始bag包。

      在播放bag包后我发现同步节点的回调函数没有被调用,结束录制命令后我通过rqt_bag synced_bag命令查看时间戳,发现没有时间戳,这证明同步未进行或者同步失败了。

      下面是我同步节点的运行日志:
      c606@ubuntu:~/fyx/e2e_ws$ ros2 run sys_time sys_time_node
      [INFO] [1752477350.845923197] [multi_sensor_sync]: 🚀 多传感器同步节点已启动 (ApproximateTime策略)
      [WARN] [1752477359.044116748] []: Messages of type 6 arrived out of order (will print only once)
      [WARN] [1752477376.810937820] []: Messages of type 3 arrived out of order (will print only once)
      [WARN] [1752477376.825926258] []: Messages of type 0 arrived out of order (will print only once)
      [WARN] [1752477376.831166002] []: Messages of type 2 arrived out of order (will print only once)
      [WARN] [1752477376.840478915] []: Messages of type 5 arrived out of order (will print only once)
      [WARN] [1752477376.891147241] []: Messages of type 1 arrived out of order (will print only once)
      [WARN] [1752477377.102514764] []: Messages of type 4 arrived out of order (will print only once)

      下面是我的同步节点代码:

      #include <rclcpp/rclcpp.hpp>
      #include <sensor_msgs/msg/image.hpp>
      #include <sensor_msgs/msg/point_cloud2.hpp>
      #include <message_filters/subscriber.h>
      #include <message_filters/synchronizer.h>
      #include <message_filters/sync_policies/approximate_time.h>
      
      using ImageMsg = sensor_msgs::msg::Image;
      using PointCloud2Msg = sensor_msgs::msg::PointCloud2;
      
      class MultiSensorSync : public rclcpp::Node {
      public:
        MultiSensorSync() : Node("multi_sensor_sync") {
          // 增强QoS配置 
          auto qos = rclcpp::SensorDataQoS()
                     .keep_last(20)       // 增大缓存队列
                     .reliable()          // 可靠传输模式
                     .durability_volatile(); // 允许历史数据
          
          initPublishers(qos);
          initSubscribersAndSync(qos);
          
          RCLCPP_INFO(this->get_logger(), "🚀 多传感器同步节点已启动 (ApproximateTime策略)");
        }
      
      private:
        void initPublishers(const rclcpp::QoS& qos) {
          for (int i = 0; i < 6; ++i) {
            cam_pubs_.push_back(
              this->create_publisher<ImageMsg>("/camera" + std::to_string(i+1) + "/synced/image_raw", qos)
            );
          }
          lidar_pub_ = this->create_publisher<PointCloud2Msg>("/rslidar_points/synced", qos);
        }
      
        void initSubscribersAndSync(const rclcpp::QoS& qos) {
          // 创建相机订阅器
          for (int i = 0; i < 6; ++i) {
            cam_subs_.push_back(
              std::make_shared<message_filters::Subscriber<ImageMsg>>(
                this, 
                "/camera" + std::to_string(i+1) + "/pylon_ros2_camera_node/image_raw",
                qos.get_rmw_qos_profile()
              )
            );
          }
          
          // 创建雷达订阅器
          lidar_sub_ = std::make_shared<message_filters::Subscriber<PointCloud2Msg>>(
            this, "/rslidar_points", qos.get_rmw_qos_profile()
          );
          
          // 配置ApproximateTime策略 
          using SyncPolicy = message_filters::sync_policies::ApproximateTime<
            ImageMsg, ImageMsg, ImageMsg, ImageMsg, ImageMsg, ImageMsg, PointCloud2Msg>;
          
          // 创建同步器(增大时间窗口)
          sync_ = std::make_shared<message_filters::Synchronizer<SyncPolicy>>(
            SyncPolicy(50),  // 队列大小增至50
            *cam_subs_[0], *cam_subs_[1], *cam_subs_[2], 
            *cam_subs_[3], *cam_subs_[4], *cam_subs_[5], 
            *lidar_sub_
          );
          
          // 注册回调并绑定生命周期
          sync_->registerCallback(
            std::bind(&MultiSensorSync::syncCallback, this, 
              std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
              std::placeholders::_4, std::placeholders::_5, std::placeholders::_6,
              std::placeholders::_7
            )
          );
        }
      
        void syncCallback(
          const ImageMsg::ConstSharedPtr& cam1,
          const ImageMsg::ConstSharedPtr& cam2,
          const ImageMsg::ConstSharedPtr& cam3,
          const ImageMsg::ConstSharedPtr& cam4,
          const ImageMsg::ConstSharedPtr& cam5,
          const ImageMsg::ConstSharedPtr& cam6,
          const PointCloud2Msg::ConstSharedPtr& lidar)
        {
          // 使用第一个相机的时间戳作为基准
          //const auto& base_stamp = cam1->header.stamp;
          const auto& base_stamp = lidar->header.stamp;
          // 发布所有相机数据(统一时间戳)
          publishWithStamp(cam_pubs_[0], cam1, base_stamp);
          publishWithStamp(cam_pubs_[1], cam2, base_stamp);
          publishWithStamp(cam_pubs_[2], cam3, base_stamp);
          publishWithStamp(cam_pubs_[3], cam4, base_stamp);
          publishWithStamp(cam_pubs_[4], cam5, base_stamp);
          publishWithStamp(cam_pubs_[5], cam6, base_stamp);
          
          // 发布雷达数据(统一时间戳)
          auto new_lidar = std::make_shared<PointCloud2Msg>(*lidar);
          new_lidar->header.stamp = base_stamp;
          lidar_pub_->publish(*new_lidar);
          
          // 修复时间戳访问方式
          RCLCPP_INFO(this->get_logger(), "🔥 同步发布 @ %d.%09d", 
                     base_stamp.sec, base_stamp.nanosec);
        }
      
        void publishWithStamp(rclcpp::Publisher<ImageMsg>::SharedPtr pub, 
                              const ImageMsg::ConstSharedPtr& msg, 
                              const builtin_interfaces::msg::Time& stamp) {
          auto new_msg = std::make_shared<ImageMsg>(*msg);
          new_msg->header.stamp = stamp;
          pub->publish(*new_msg);
        }
      
        // 成员变量
        std::vector<rclcpp::Publisher<ImageMsg>::SharedPtr> cam_pubs_;
        std::vector<std::shared_ptr<message_filters::Subscriber<ImageMsg>>> cam_subs_;
        rclcpp::Publisher<PointCloud2Msg>::SharedPtr lidar_pub_;
        std::shared_ptr<message_filters::Subscriber<PointCloud2Msg>> lidar_sub_;
        
        using SyncPolicy = message_filters::sync_policies::ApproximateTime<
          ImageMsg, ImageMsg, ImageMsg, ImageMsg, ImageMsg, ImageMsg, PointCloud2Msg>;
        std::shared_ptr<message_filters::Synchronizer<SyncPolicy>> sync_;
      };
      
      int main(int argc, char** argv) {
        rclcpp::init(argc, argv);
        rclcpp::executors::MultiThreadedExecutor executor;
        auto node = std::make_shared<MultiSensorSync>();
        executor.add_node(node);
        executor.spin();
        rclcpp::shutdown();
        return 0;
      }
      

      最后还有一点,我录制的原始bag中相机和雷达的频率在10hz左右,下面是原始bag中的时间戳截图:
      Screenshot from 2025-07-14 00-46-07.png

      1 条回复 最后回复 回复 引用 0
      • 第一个帖子
        最后一个帖子
      皖ICP备16016415号-7
      Powered by NodeBB | 鱼香ROS