小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
ROS2 订阅高帧率的话题的时间滞后于低帧率话题的时间
-
一个节点同时订阅200Hz的imu和10Hz的点云数据,且只做打印时间戳的操作,但是会出现连续收到几帧点云数据后才收到imu数据,且发布端是没有问题的,出问题的点云数据的时间是在imu数据之后的
#include <glog/logging.h> #include <iomanip> #include <rclcpp/rclcpp.hpp> #include <sensor_msgs/msg/imu.hpp> #include <sensor_msgs/msg/point_cloud2.hpp> double FromRos(builtin_interfaces::msg::Time time) { return time.sec + 1e-9 * time.nanosec; } class SimpleSubscriber : public rclcpp::Node { public: SimpleSubscriber() : Node("simple_subscriber") { FLAGS_colorlogtostderr = true; // 显示颜色 FLAGS_alsologtostderr = 1; // 终端与文件共同输出 google::InitGoogleLogging("simple_subscriber"); google::SetLogDestination(google::INFO, "/opt/eame/log/simple_subscriber/"); FLAGS_minloglevel = google::INFO; point_cloud_subscription_ = this->create_subscription<sensor_msgs::msg::PointCloud2>( "/livox/lidar", 5, std::bind(&SimpleSubscriber::HandlePointCloud2Message, this, std::placeholders::_1)); imu_subscription_ = this->create_subscription<sensor_msgs::msg::Imu>( "/livox/imu", 2000, std::bind(&SimpleSubscriber::HandleImuMessage, this, std::placeholders::_1)); } private: void HandlePointCloud2Message(const sensor_msgs::msg::PointCloud2::SharedPtr msg) { const double lidar_stamp = FromRos(msg->header.stamp); if (last_lidar_stamp_) { const double delta_time = lidar_stamp - *last_lidar_stamp_; LOG_IF(ERROR, delta_time > 0.12) << "delta_time is " << delta_time << ", lidar_stamp: " << std::fixed << std::setprecision(3) << lidar_stamp << ", last_lidar_stamp_: " << std::fixed << std::setprecision(3) << *last_lidar_stamp_; } last_lidar_stamp_ = std::make_unique<double>(lidar_stamp); LOG(INFO) << "lidar time: " << std::fixed << std::setprecision(3) << FromRos(msg->header.stamp); LOG_IF(WARNING, !imu_is_comming_) << "Imu data is later."; imu_is_comming_ = false; }![订阅器.png](/forum/assets/uploads/files/1718777955759-订阅器.png) void HandleImuMessage(const sensor_msgs::msg::Imu::SharedPtr msg) { imu_is_comming_ = true; LOG(INFO) << "imu time: " << std::fixed << std::setprecision(3) << FromRos(msg->header.stamp); } rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr point_cloud_subscription_; rclcpp::Subscription<sensor_msgs::msg::Imu>::SharedPtr imu_subscription_; bool imu_is_comming_ = true; std::unique_ptr<double> last_lidar_stamp_; }; int main(int argc, char *argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<SimpleSubscriber>()); rclcpp::shutdown(); return 0; }
该订阅器的日志:
发布器的日志
订阅器日志中“Imu data is later”处表示连续收到几帧点云后,才收到之前已经发布的imu数据,且发布器日志中该时间段内imu数据在正常发布,发布时间与本身时间戳并无过大差别。
各位大佬,请问这是什么原因导致的,有无办法解决?
-
你遇到的问题可能涉及到ROS 2中的消息传递和时间同步。由于ROS 2是分布式系统,节点之间的消息传递并不是实时的,且可能会受到系统负载、网络延迟和消息队列的影响。下面是一些可能导致你看到的现象的原因以及可能的解决方案:
可能的原因
-
消息队列大小:你的IMU订阅器设置了队列大小为2000,而点云订阅器队列大小为5。如果IMU数据生成得太快,而处理速度跟不上,那么IMU消息可能会在队列中堆积,导致接收时间延迟。
-
处理时间:如果
HandleImuMessage
或HandlePointCloud2Message
的回调函数中花费的时间太长,那么新的消息可能会在回调处理完成之前就被阻塞。 -
系统调度:ROS 2节点可能受到操作系统调度策略的影响,导致某些节点的回调处理被延迟。
-
时间同步:ROS 2使用模拟时钟或系统时钟,如果时钟不同步或存在漂移,可能导致时间戳的误解。
可能的解决方案
-
调整队列大小:根据实际的硬件能力和需求调整队列大小。过大的队列可能导致内存消耗过高,而过小的队列可能导致消息丢失。
-
优化处理时间:确保回调函数中的操作尽可能高效,避免不必要的计算或I/O操作。
-
使用QoS策略:ROS 2提供了QoS(Quality of Service)策略来控制消息传递的可靠性、持久性和深度。你可以尝试调整这些策略来改善性能。
-
确保时间同步:使用NTP(Network Time Protocol)或其他时间同步机制确保所有ROS 2节点的时间同步。
-
使用消息过滤器:你可以使用如
message_filters
这样的包来同步不同频率的消息。这对于需要精确时间对齐的应用(如传感器融合)非常有用。 -
检查ROS 2版本和配置:确保你使用的ROS 2版本是稳定的,并且配置是正确的。某些版本或配置可能存在已知的性能问题。
-
分析性能:使用ROS 2的性能分析工具(如
ros2 topic hz
、ros2 bag
等)来检查系统的性能瓶颈。
注意事项
- 确保你的IMU和点云发布器的时间戳是准确的,并且与ROS 2的时间同步。
- 检查你的ROS 2网络设置,确保没有网络瓶颈或延迟。
- 如果可能的话,尝试在不同的硬件或网络环境下运行你的系统,以排除硬件或网络问题的可能性。
最后,记住ROS 2是一个复杂的分布式系统,涉及到许多不同的组件和配置。解决性能问题可能需要一些时间和耐心。通过系统地分析和优化你的系统,你应该能够找到导致问题的根本原因,并找到有效的解决方案。
以上为生成回答,仅供参考~
-
-
补充:
订阅器日志:发布器日志:
-
兄弟,这个问题最后有解决吗,我们也遇到了同样的问题