livox_ros_driver2 icon indicating copy to clipboard operation
livox_ros_driver2 copied to clipboard

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

Open yunmango opened this issue 1 year ago • 11 comments

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 avatar Jul 05 '23 19:07 yunmango

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.

yunmango avatar Jul 05 '23 19:07 yunmango

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

georgflick avatar Jul 13 '23 12:07 georgflick

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.

JeiKeiLim avatar Jul 19 '23 00:07 JeiKeiLim

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

David-Willo avatar Jul 19 '23 02:07 David-Willo

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.

hg-zt avatar Jul 20 '23 06:07 hg-zt

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

dasol-aero avatar Jul 24 '23 04:07 dasol-aero

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  ...

JeiKeiLim avatar Jul 24 '23 05:07 JeiKeiLim

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

dasol-aero avatar Jul 24 '23 10:07 dasol-aero

Same Question

ToutDonner avatar Jul 29 '23 11:07 ToutDonner

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.

Call-Me-Jesse avatar Aug 18 '23 07:08 Call-Me-Jesse

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.

JulioPlaced avatar Apr 11 '24 06:04 JulioPlaced