Get out PCD in real time using Livox-SDK. Converting LivoxEthPacket to raw point in real time. #133

Open
opened 2021-07-15 11:51:50 +02:00 by palffybalazs · 10 comments
palffybalazs commented 2021-07-15 11:51:50 +02:00 (Migrated from github.com)

Dear All, @Livox-SDK
I am working on collecting pcd in real time, however my solution is inefficient. The number of points I can extract using the SDK is very low compared to the sensor's parameters.
Main goal: Collecting data in a pcl::pointcloud for an optional period of time.

Tried possible solutions:

  • I modified GetLidarData function in lidar_lvx_sample -> main.cpp. As far as I know LivoxEthPacket contains 100 points with 13byte space, so this needs some postproccessing to achive the rawpoints. This can be done by using offsets and shifting bits, furthermore I used multiple threads to work on this, so theoretically it does not slow down as much the main thread, but even with this solution, it seems like it cant catch up in speed. For 100ms I get apr. 1500 points. This is very low.
    Part of the code (cloud is global and cleared time for time):
    void ConvertToPoint(LivoxEthPacket *data, int i) {
    pcl::PointXYZI point;
    int x = (int32_t)((data->data[i]) + (data->data[i + 1] << 8) + (data->data[i + 2] << 16) + (data->data[i + 3] << 24));
    int y = (int32_t)((data->data[i + 4]) + (data->data[i + 5] << 8) + (data->data[i + 6] << 16) + (data->data[i + 7] << 24));
    int z = (int32_t)((data->data[i + 8]) + (data->data[i + 9] << 8) + (data->data[i + 10] << 16) + (data->data[i + 11] << 24));
    int intensity = (uint8_t)data->data[i + 12];
    point.x = x;
    point.y = y;
    point.z = z;
    point.intensity = intensity;
    mylock.lock();
    cloud->push_back(point);
    mylock.unlock();
    }
    This is in GetLidarData:
    for (int i = 0; i < 1300; i += 14)// 100 points * 13byte space
    {
    threads.emplace_back([&]() {ConvertToPoint(data, i); });
    }
    for (auto& t : threads)
    {
    t.join();
    }

And after a time, I did save on a different thread, but saving is not that important, I did that just for checking the cloud's correctness.

  • I tried other possible solutions, like extracting the data after a given amount of time like the SDK does with the point_packet_list in the same file's main function and after in lvx_file.cpp with the offsets in function SaveFrameToLvxFile. That did not help me out either.
    It seems like, it just throws the data in a file and does nothing to it but just copying and making headers.

My questions:
How can LivoxViewer achive real time visualizing with the postproccessing of the packets? How can I achive that goal? I just want to collect points in a pcl::pointcloud for given time without missing out data(points). Is there a good solution for that?
That is my main goal.
I checked the other issues, did not really help me.

Currently, I am using Livox Avia LiDAR sensor.
Windows 10 and also Ubuntu in case if it is needed.
Thank you for your help in advance
Best regards.

Dear All, @Livox-SDK I am working on collecting pcd in real time, however my solution is inefficient. The number of points I can extract using the SDK is very low compared to the sensor's parameters. **Main goal: Collecting data in a pcl::pointcloud for an optional period of time.** Tried possible solutions: - I modified GetLidarData function in lidar_lvx_sample -> main.cpp. As far as I know LivoxEthPacket contains 100 points with 13byte space, so this needs some postproccessing to achive the rawpoints. This can be done by using offsets and shifting bits, furthermore I used multiple threads to work on this, so theoretically it does not slow down as much the main thread, but even with this solution, it seems like it cant catch up in speed. For 100ms I get apr. 1500 points. This is very low. Part of the code (cloud is global and cleared time for time): `void ConvertToPoint(LivoxEthPacket *data, int i) {` `pcl::PointXYZI point; ` `int x = (int32_t)((data->data[i]) + (data->data[i + 1] << 8) + (data->data[i + 2] << 16) + (data->data[i + 3] << 24));` `int y = (int32_t)((data->data[i + 4]) + (data->data[i + 5] << 8) + (data->data[i + 6] << 16) + (data->data[i + 7] << 24));` `int z = (int32_t)((data->data[i + 8]) + (data->data[i + 9] << 8) + (data->data[i + 10] << 16) + (data->data[i + 11] << 24));` `int intensity = (uint8_t)data->data[i + 12];` `point.x = x;` `point.y = y;` `point.z = z;` `point.intensity = intensity;` `mylock.lock();` `cloud->push_back(point);` `mylock.unlock();` `}` **This is in GetLidarData:** `for (int i = 0; i < 1300; i += 14)// 100 points * 13byte space` `{` ` threads.emplace_back([&]() {ConvertToPoint(data, i); });` `}` `for (auto& t : threads)` ` {` ` t.join();` `}` And after a time, I did save on a different thread, but saving is not that important, I did that just for checking the cloud's correctness. - I tried other possible solutions, like extracting the data after a given amount of time like the SDK does with the point_packet_list in the same file's main function and after in lvx_file.cpp with the offsets in function SaveFrameToLvxFile. That did not help me out either. It seems like, it just throws the data in a file and does nothing to it but just copying and making headers. **My questions:** How can LivoxViewer achive real time visualizing with the postproccessing of the packets? How can I achive that goal? I just want to collect points in a pcl::pointcloud for given time without missing out data(points). Is there a good solution for that? That is my main goal. I checked the other issues, did not really help me. Currently, I am using Livox Avia LiDAR sensor. Windows 10 and also Ubuntu in case if it is needed. Thank you for your help in advance Best regards.
Livox-SDK commented 2021-07-16 13:32:40 +02:00 (Migrated from github.com)

Hi @palffybalazs
It's recommended to cache LivoxEthPacket*data to buffers like point_packet_list and start a timer on another thread to convert point_packet_list to pcl::pointcloud. e.g.

void LvxFileHandle::SaveFrameToLvxFile(std::list<LvxBasePackDetail> &point_packet_list) {
   for (const auto &point_pack : point_packet_list) {
      if (point_pack.data_type == kExtendCartesian) {
            LivoxExtendRawPoint *p_point_data = (LivoxExtendRawPoint *)point_pack.raw_data;
            for (int i = 0; i < 96; i++) {
                 //Todo Convert p_point_data[i] to pcl::pointcloud
           }
      }
   }
}
Hi @palffybalazs It's recommended to cache `LivoxEthPacket*data` to buffers like `point_packet_list` and start a timer on another thread to convert `point_packet_list` to `pcl::pointcloud`. e.g. ``` void LvxFileHandle::SaveFrameToLvxFile(std::list<LvxBasePackDetail> &point_packet_list) { for (const auto &point_pack : point_packet_list) { if (point_pack.data_type == kExtendCartesian) { LivoxExtendRawPoint *p_point_data = (LivoxExtendRawPoint *)point_pack.raw_data; for (int i = 0; i < 96; i++) { //Todo Convert p_point_data[i] to pcl::pointcloud } } } } ```
yuyu19970716 commented 2021-07-29 08:40:31 +02:00 (Migrated from github.com)

Hello, when I was running lidar_lvx_sample, I found that I could only get the radar data in units of s, I wanted to get the radar data of 0.2s, then I looked in main. cpp and lvx_file. cpp to see where to modify, but I didn't find it, could you please tell me where to modify? Thank you very much!

Hello, when I was running lidar_lvx_sample, I found that I could only get the radar data in units of s, I wanted to get the radar data of 0.2s, then I looked in main. cpp and lvx_file. cpp to see where to modify, but I didn't find it, could you please tell me where to modify? Thank you very much!
palffybalazs commented 2021-07-29 09:39:28 +02:00 (Migrated from github.com)

Hi,
If I get you right, you want to collect the data in some container or process it based on time.
You can do this by modifying the main.cpp, where the SDK calls the "lvx_file_handler.SaveFrameToLvxFile(point_packet_list_temp);" function. You can write your own function to the stuff you want to.
For example you can collect the data in it with a pcl::poinctloud. Also, you can start a timer in the code, refresh it, and based on that you can save or process the collected data.

Write a function.
Call it with the point_packet_list_temp as a parameter.
Process the data in the function and collect it in a container.
Based on a timer you can save it or etc (Should do this on a thread).
Example code

double startTime = GetTickCount();
int MS = 200;
void YourFunctionGoesHere(std::list<LvxBasePackDetail> &point_packet_list_temp) {
currentTime = GetTickCount() - startTime;
//Collect the data for a given time in a container or proccess it.

`if (currentTime > MS) {
	startTime = GetTickCount();
	//Do whatever you want with the collected data
 }
 }`
 
 
 int main(int argc, const char *argv[]) {
 //SDK stuff happens........
 std::list<LvxBasePackDetail> point_packet_list_temp;
	{
		std::unique_lock<std::mutex> lock(mtx);
		point_pack_condition.wait_for(lock, milliseconds(kDefaultFrameDurationTime) - (steady_clock::now() - last_time));
		last_time = steady_clock::now();

		
		point_packet_list_temp.swap(point_packet_list);
	
	}
	std::thread YourFunction(YourFunctionGoesHere, point_packet_list_temp);
	YourFunction.detach();
 }

Good luck,
Sorry if I misunderstood you.

Hi, If I get you right, you want to collect the data in some container or process it based on time. You can do this by modifying the main.cpp, where the SDK calls the "lvx_file_handler.SaveFrameToLvxFile(point_packet_list_temp);" function. You can write your own function to the stuff you want to. For example you can collect the data in it with a pcl::poinctloud. Also, you can start a timer in the code, refresh it, and based on that you can save or process the collected data. Write a function. Call it with the point_packet_list_temp as a parameter. Process the data in the function and collect it in a container. Based on a timer you can save it or etc (Should do this on a thread). Example code ` double startTime = GetTickCount();` ` int MS = 200;` ` void YourFunctionGoesHere(std::list<LvxBasePackDetail> &point_packet_list_temp) {` ` currentTime = GetTickCount() - startTime;` ` //Collect the data for a given time in a container or proccess it. ` `if (currentTime > MS) { startTime = GetTickCount(); //Do whatever you want with the collected data } }` int main(int argc, const char *argv[]) { //SDK stuff happens........ std::list<LvxBasePackDetail> point_packet_list_temp; { std::unique_lock<std::mutex> lock(mtx); point_pack_condition.wait_for(lock, milliseconds(kDefaultFrameDurationTime) - (steady_clock::now() - last_time)); last_time = steady_clock::now(); point_packet_list_temp.swap(point_packet_list); } std::thread YourFunction(YourFunctionGoesHere, point_packet_list_temp); YourFunction.detach(); } Good luck, Sorry if I misunderstood you.
yuyu19970716 commented 2021-07-29 09:48:26 +02:00 (Migrated from github.com)

Oh! Thank you very much for your reply! I will read it carefully, I think it is helpful!

Good luck!

Oh! Thank you very much for your reply! I will read it carefully, I think it is helpful! Good luck!
yuyu19970716 commented 2021-07-31 15:59:55 +02:00 (Migrated from github.com)

Hello, thank you very much for your last answer! I think your explanation is very clear! I have another question to ask you. If I want to directly connect the radar to get the radar point cloud data in my Python program, and then operate the data without saving it as an LVX file, I need to call the SDK library function, but I don't have a clue here. I think I need to run the sample / lidar / main. C file this time and there is the package data in this file, I just put main.c and livox_ sdk.h in this file directly and I just run them in my code. I think it's wrong to do so. So I especially hope you can give me some guidance. If it's convenient for you, thank you very much!

Hello, thank you very much for your last answer! I think your explanation is very clear! I have another question to ask you. If I want to directly connect the radar to get the radar point cloud data in my Python program, and then operate the data without saving it as an LVX file, I need to call the SDK library function, but I don't have a clue here. I think I need to run the sample / lidar / main. C file this time and there is the package data in this file, I just put main.c and livox_ sdk.h in this file directly and I just run them in my code. I think it's wrong to do so. So I especially hope you can give me some guidance. If it's convenient for you, thank you very much!
palffybalazs commented 2021-08-01 10:21:40 +02:00 (Migrated from github.com)

Hi,
To do this, you can use the files you already modified. I used lidar_lvx_sample and main.cpp to do that. Livox-SDK\sample\lidar_lvx_file. You can comment out the original LVX saving method's call, then its not going to save it in .lvx.
Also, you already managed to collect the data with the first question of yours, with your own function with parameterized time I assume. Then you can process it with a new thread. My advice, to modifie the loop in the main, for example to a while loop, then it is not going to stop after a few round.

Also, you can do this in the files you mentioned. Actually you can change main.c to main .cpp by renaming in sample / lidar / main. C, then you can import and use your already installed cpp libs. Both files can do the collection and processing stuff I think.

By the way, I dont really know how you installed this sdk. You should be able to run the part without putting the files anyhere. You just follow the installation guide from the main page. After that, you just need to build the project you want to run everytime you modify it. Then, you get an .exe in the corresponding file in the build file in case you use windows.
On Linux, you can do this with the command line.

However, I dont really know how could you use the python program with this SDK. Maybe you can turn it to a c++ code if it is not that long or complex, or use this Python SDK instead of Livox-SDK. The problem with the mention Python SDK is, that it is tested only on one type of Livox sensor called Mid40. If you have that, no problem, other case you need to modify the code.

Hope it helps,
Best regards.

Hi, To do this, you can use the files you already modified. I used lidar_lvx_sample and main.cpp to do that. Livox-SDK\sample\lidar_lvx_file. You can comment out the original LVX saving method's call, then its not going to save it in .lvx. Also, you already managed to collect the data with the first question of yours, with your own function with parameterized time I assume. Then you can process it with a new thread. My advice, to modifie the loop in the main, for example to a while loop, then it is not going to stop after a few round. Also, you can do this in the files you mentioned. Actually you can change main.c to main .cpp by renaming in sample / lidar / main. C, then you can import and use your already installed cpp libs. Both files can do the collection and processing stuff I think. By the way, I dont really know how you installed this sdk. You should be able to run the part without putting the files anyhere. You just follow the installation guide from the main page. After that, you just need to build the project you want to run everytime you modify it. Then, you get an .exe in the corresponding file in the build file in case you use windows. On Linux, you can do this with the command line. However, I dont really know how could you use the python program with this SDK. Maybe you can turn it to a c++ code if it is not that long or complex, or use this [Python SDK](https://github.com/Livox-SDK/openpylivox) instead of Livox-SDK. The problem with the mention Python SDK is, that it is tested only on one type of Livox sensor called Mid40. If you have that, no problem, other case you need to modify the code. Hope it helps, Best regards.
yuyu19970716 commented 2021-08-02 03:13:06 +02:00 (Migrated from github.com)

Hello!

Thank you very much for your proposal! My lidar is indeed Livox mid 40, now on Ubuntu I don't want to use the command line to extract the radar data, now I want to directly turn on the radar in my program and get the data, I don't know much about C ++, I think I will try to change my program to C or try using the Python SDK. Because eventually my code is all changed to C language or C ++! Thank you very much! I wish you all the best!

Best wishes to you!

Hello! Thank you very much for your proposal! My lidar is indeed Livox mid 40, now on Ubuntu I don't want to use the command line to extract the radar data, now I want to directly turn on the radar in my program and get the data, I don't know much about C ++, I think I will try to change my program to C or try using the Python SDK. Because eventually my code is all changed to C language or C ++! Thank you very much! I wish you all the best! Best wishes to you!
qiemy commented 2024-03-11 07:42:08 +01:00 (Migrated from github.com)

Hello!
Have you solved this problem?I also need get pcd data in real time but I'm not good in C++. I would appreciate it if you could share your solution!

Hello! Have you solved this problem?I also need get pcd data in real time but I'm not good in C++. I would appreciate it if you could share your solution!
palffybalazs commented 2024-03-11 13:10:59 +01:00 (Migrated from github.com)

Hello!
Honestly, I would recommend the usage of livox ros instead of using this kind of exportation from the livox sdk.
In that case it is possible to set the integration time of the clouds and it runs at real time (as you mentioned).
Furthermore, ros is using nodes, subscribe and publish policy, and also gives flexibility with the choice of programming languages.
https://github.com/Livox-SDK/livox_ros_driver
All the best!

Hello! Honestly, I would recommend the usage of livox ros instead of using this kind of exportation from the livox sdk. In that case it is possible to set the integration time of the clouds and it runs at real time (as you mentioned). Furthermore, ros is using nodes, subscribe and publish policy, and also gives flexibility with the choice of programming languages. https://github.com/Livox-SDK/livox_ros_driver All the best!
qiemy commented 2024-03-11 13:32:21 +01:00 (Migrated from github.com)

Hello! Honestly, I would recommend the usage of livox ros instead of using this kind of exportation from the livox sdk. In that case it is possible to set the integration time of the clouds and it runs at real time (as you mentioned). Furthermore, ros is using nodes, subscribe and publish policy, and also gives flexibility with the choice of programming languages. https://github.com/Livox-SDK/livox_ros_driver All the best!

Thank you for your valuable suggestion!
I also want to use ros for its convinence.But unluckly, the project I'm working on doesn't allow me to use Ros. In this project I need get pcd data from lidar and then send them to a python program through FAST-DDS. So I have to modify the sdk example itself. Your excellent idea in this issue gives me some inspiration!

> Hello! Honestly, I would recommend the usage of livox ros instead of using this kind of exportation from the livox sdk. In that case it is possible to set the integration time of the clouds and it runs at real time (as you mentioned). Furthermore, ros is using nodes, subscribe and publish policy, and also gives flexibility with the choice of programming languages. https://github.com/Livox-SDK/livox_ros_driver All the best! Thank you for your valuable suggestion! I also want to use ros for its convinence.But unluckly, the project I'm working on doesn't allow me to use Ros. In this project I need get pcd data from lidar and then send them to a python program through FAST-DDS. So I have to modify the sdk example itself. Your excellent idea in this issue gives me some inspiration!
This repo is archived. You cannot comment on issues.
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mmr/Livox-SDK#133