Livox-SDK / livox_ros_driver2

Livox device driver under Ros(Compatible with ros and ros2), support Lidar HAP and Mid-360.
Other
200 stars 161 forks source link

Issue with Inconsistent Publishing Frequency of PointCloud Messages in ROS1 using Livox Mid-360 LiDAR #56

Open yunmango opened 1 year ago

yunmango commented 1 year ago

I've been working with the Livox Mid-360 LiDAR in ROS1. However, I've encountered an issue where the PointCloud messages are not being published at a consistent rate. The publishing frequency varies between 6Hz and 10Hz, which is not what I expected.

yunmango commented 1 year ago

In the Livox Viewer, the PointCloud messages appear to be published consistently. However, when operating in ROS, this consistency isn't observed. Could you assist with this discrepancy as well? Thank you.

georgflick commented 12 months ago

maybe the hardware, where you are running the ros driver is not powerful enough?

JeiKeiLim commented 11 months ago

Same situation here. I've tested on Jetson Xavier NX and RPi4 on ROS1 Noetic. NX was about 5\~10Hz and RPi was about 7\~10Hz.

Also I have tried to increase publish_freq by 20 and it mostly maintains Hz about 20\~19 but sometimes it drops to 7\~15.

BTW, this issue never occurred when I was using Livox AVIA which uses livox_ros_driver and I believe that the amount of the data is larger with AVIA. Also tested on NX and RPi4.

+ I just tested on Xeon 6240 workstation and it shows same problem. So definitely not a hardware issue. I wonder ROS2 does not have this issue.

David-Willo commented 11 months ago

I have similar issue here testing Mid-360 on Jetson agx Orin Ubuntu 20.04 and another computer with i7-8700 Ubuntu18.04. The point cloud frequency drops to 7~8 Hz occasionally. image

hg-zt commented 11 months ago

I found closing rviz while cooling the lidar makes the publishing frequency more stable. But the problem still occur sometimes. Maybe it's caused by multiple reasons.

dasol-aero commented 11 months ago

I have same issue with my Mid-360 on ROS2 Humble. Publishing Hz is really inconsistent.

JeiKeiLim commented 11 months ago

I believe I found a temporary solution. It's caused by checking publishing interval in millisecond. In the 161 ~ 163 lines of pub_handler.cpp, recent_time_ms is checked if it is modded with publish_interval_ms (which is 100 by default) by zero. CheckTimer seems to be called more than once by every millisecond usually but that's not the every case as we have observed above. So if CheckTimer misses this recent_time_ms % publish_interval_ms, it has no other option but to wait until the next publish_interval_ms.

I think that the reason of recent_time_ms % publish_interval_ms is to synchronize lidar point times but it creates this unstable Hz issue. My question to @Livox-SDK dev team is that what's the side effect of removing 161~163 lines as I wrote below from Original to Modified.

Original pub_handler.cpp

156  void PubHandler::CheckTimer() {
157  uint8_t lidar_number = lidar_process_handlers_.size();
158  
159  for (auto &process_handler : lidar_process_handlers_) {
160    uint64_t recent_time_ms = process_handler.second->GetRecentTimeStamp() / kRatioOfMsToNs;
161     if ((recent_time_ms % publish_interval_ms_ != 0) || recent_time_ms == 0) {
162      continue;
163    }
164 
165    uint64_t diff = process_handler.second->GetRecentTimeStamp() - process_handler.second->GetLidarBaseTime();
166    if (diff < publish_interval_tolerance_) {
167      continue;
168    }
169  ...

Modified pub_handler.cpp

156  void PubHandler::CheckTimer() {
157  uint8_t lidar_number = lidar_process_handlers_.size();
158  
159  for (auto &process_handler : lidar_process_handlers_) {
160    uint64_t recent_time_ms = process_handler.second->GetRecentTimeStamp() / kRatioOfMsToNs;
161    // if ((recent_time_ms % publish_interval_ms_ != 0) || recent_time_ms == 0) {
162    //   continue;
163    // }
164 
165    uint64_t diff = process_handler.second->GetRecentTimeStamp() - process_handler.second->GetLidarBaseTime();
166    if (diff < publish_interval_tolerance_) {
167      continue;
168    }
169  ...
dasol-aero commented 11 months ago

@JeiKeiLim I have tested your solution (Mid-360 & ROS 2 Humble). It seems to work well for me. Thank you for sharing!

ToutDonner commented 11 months ago

Same Question

Call-Me-Jesse commented 10 months ago

I believe I found a temporary solution. It's caused by checking publishing interval in millisecond. In the 161 ~ 163 lines of pub_handler.cpp, recent_time_ms is checked if it is modded with publish_interval_ms (which is 100 by default) by zero. CheckTimer seems to be called more than once by every millisecond usually but that's not the every case as we have observed above. So if CheckTimer misses this recent_time_ms % publish_interval_ms, it has no other option but to wait until the next publish_interval_ms.

I think that the reason of recent_time_ms % publish_interval_ms is to synchronize lidar point times but it creates this unstable Hz issue. My question to @Livox-SDK dev team is that what's the side effect of removing 161~163 lines as I wrote below from Original to Modified.

Original pub_handler.cpp

156  void PubHandler::CheckTimer() {
157  uint8_t lidar_number = lidar_process_handlers_.size();
158  
159  for (auto &process_handler : lidar_process_handlers_) {
160    uint64_t recent_time_ms = process_handler.second->GetRecentTimeStamp() / kRatioOfMsToNs;
161     if ((recent_time_ms % publish_interval_ms_ != 0) || recent_time_ms == 0) {
162      continue;
163    }
164 
165    uint64_t diff = process_handler.second->GetRecentTimeStamp() - process_handler.second->GetLidarBaseTime();
166    if (diff < publish_interval_tolerance_) {
167      continue;
168    }
169  ...

Modified pub_handler.cpp

156  void PubHandler::CheckTimer() {
157  uint8_t lidar_number = lidar_process_handlers_.size();
158  
159  for (auto &process_handler : lidar_process_handlers_) {
160    uint64_t recent_time_ms = process_handler.second->GetRecentTimeStamp() / kRatioOfMsToNs;
161    // if ((recent_time_ms % publish_interval_ms_ != 0) || recent_time_ms == 0) {
162    //   continue;
163    // }
164 
165    uint64_t diff = process_handler.second->GetRecentTimeStamp() - process_handler.second->GetLidarBaseTime();
166    if (diff < publish_interval_tolerance_) {
167      continue;
168    }
169  ...

I think the code you commented is used to control the publish frequency, because every udp packet received CheckTimer function will be called, if you comment out here, I think the publish frequency will become very high.

JulioPlaced commented 2 months ago

Same issue here, identified for Livox HAP and ROS2 Humble: some clouds are not published which makes the frequency unstable. Moreover, the unpublished cloud(s) are not lost, they are concatenated and this makes some published clouds to have 2x or 3x the usual cloud size.

The solution provided by @JeiKeiLim seems to have fixed the issue.