image_framework_ymj/image_framework/driver/livox/LidarHelper.cpp
2024-12-06 16:25:16 +08:00

342 lines
11 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _WIN32
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <string.h>
#include "LidarHelper.h"
CLidarHelper* CLidarHelper::m_instance;
extern "C" {
/** 回调函数声明 */
static void OnLidarErrorStatusCallback(livox_status status, uint8_t handle, ErrorMessage* message);
static void GetLidarData(uint8_t handle, LivoxEthPacket* data, uint32_t data_num, void* client_data);
static void OnSampleCallback(livox_status status, uint8_t handle, uint8_t response, void* data);
static void OnCommonCommandCallback(livox_status status, uint8_t handle, uint8_t response, void* data);
static void OnStopSampleCallback(livox_status status, uint8_t handle, uint8_t response, void* data);
static void OnDeviceInfoChange(const DeviceInfo* info, DeviceEvent type);
static void OnDeviceBroadcast(const BroadcastDeviceInfo* info);
/** 用于Python的回调函数指针 */
//static void (*python_data_callback)(uint8_t, uint32_t*, uint32_t) = NULL;
//static void (*python_error_callback)(livox_status, uint8_t, ErrorMessage*) = NULL;
//static void (*python_device_change_callback)(const DeviceInfo*, DeviceEvent) = NULL;
//static void (*python_device_broadcast_callback)(const BroadcastDeviceInfo*) = NULL;
//static void (*python_common_command_callback)(livox_status, uint8_t, uint8_t) = NULL;
typedef enum {
kDeviceStateDisconnect = 0,
kDeviceStateConnect = 1,
kDeviceStateSampling = 2,
} DeviceState;
typedef struct {
uint8_t handle;
DeviceState device_state;
DeviceInfo info;
} DeviceItem;
static DeviceItem devices[kMaxLidarCount];
static int lidar_count = 0;
static FuncGetLidarData pfuncGetLidarData = nullptr;
static bool init_sdk() {
printf("Livox SDK initializing.\n");
if (!Init()) {
return false;
}
printf("Livox SDK has been initialized.\n");
LivoxSdkVersion _sdkversion;
GetLivoxSdkVersion(&_sdkversion);
printf("Livox SDK version %d.%d.%d .\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
memset(devices, 0, sizeof(devices));
return true;
}
/** 启动设备扫描 */
static bool start_discovery() {
SetBroadcastCallback(OnDeviceBroadcast);
SetDeviceStateUpdateCallback(OnDeviceInfoChange);
if (!Start()) {
printf("Failed to start device discovery.\n");
Uninit();
return false;
}
printf("Started device discovery.\n");
return true;
}
/** 停止SDK并清理 */
static void stop_sdk() {
printf("Stopping Livox SDK.\n");
for (int i = 0; i < kMaxLidarCount; ++i) {
if (devices[i].device_state == kDeviceStateSampling) {
LidarStopSampling(devices[i].handle, OnStopSampleCallback, NULL);
}
}
Uninit();
}
static int connect(const char* broadcast_code) {
uint8_t handle = 0;
livox_status result = AddLidarToConnect(broadcast_code, &handle);
if (result == kStatusSuccess) {
/** Set the point cloud data for a specific Livox LiDAR. */
SetDataCallback(handle, pfuncGetLidarData, NULL);
}
return result;
}
static int start_sampling(uint8_t handle) {
livox_status result = LidarStartSampling(handle, OnSampleCallback, NULL);
devices[handle].device_state = kDeviceStateSampling;
return result;
}
static int stop_sampling(uint8_t handle) {
livox_status result = LidarStopSampling(handle, OnSampleCallback, NULL);
devices[handle].device_state = kDeviceStateSampling;
return result;
}
static int set_mode(LidarMode mode) {
return LidarSetMode(devices[0].handle, mode, OnCommonCommandCallback, NULL);
}
/** 回调函数的定义 */
static void OnLidarErrorStatusCallback(livox_status status, uint8_t handle, ErrorMessage* message) {
//if (python_error_callback) {
// python_error_callback(status, handle, message);
//}
}
static void OnCommonCommandCallback(livox_status status, uint8_t handle, uint8_t response, void* data) {
//if (python_common_command_callback) {
// python_common_command_callback(status, handle, response);
//}
}
static void GetLidarData(uint8_t handle, LivoxEthPacket* data, uint32_t data_num, void* client_data) {
if (data) {
/** Parsing the timestamp and the point cloud data. */
uint64_t cur_timestamp = *((uint64_t*)(data->timestamp));
if (data->data_type == kCartesian) {
LivoxRawPoint* p_point_data = (LivoxRawPoint*)data->data;
}
else if (data->data_type == kSpherical) {
LivoxSpherPoint* p_point_data = (LivoxSpherPoint*)data->data;
}
else if (data->data_type == kExtendCartesian) {
LivoxExtendRawPoint* p_point_data = (LivoxExtendRawPoint*)data->data;
#ifdef _WIN32
LivoxExtendRawPoint point_array[10*10000];
#else
LivoxExtendRawPoint point_array[data_num];
#endif
uint32_t* converted_data = (uint32_t*)malloc(data_num * 4 * sizeof(uint32_t));
for (uint32_t i = 0; i < data_num; ++i) {
LivoxExtendRawPoint* point = &p_point_data[i];
// 将结构体的 x, y, z 放入 uint32_t 数组中
converted_data[i * 4] = point->x;
converted_data[i * 4 + 1] = point->y;
converted_data[i * 4 + 2] = point->z;
// 将 reflectivity 和 tag 合并成一个 uint32_t高16位和低16位
converted_data[i * 4 + 3] = (uint32_t)(point->reflectivity << 8 | point->tag);
}
//// 调用 Python 回调函数
//if (python_data_callback) {
// python_data_callback(handle, converted_data, data_num);
//}
}
else if (data->data_type == kExtendSpherical) {
LivoxExtendSpherPoint* p_point_data = (LivoxExtendSpherPoint*)data->data;
}
else if (data->data_type == kDualExtendCartesian) {
LivoxDualExtendRawPoint* p_point_data = (LivoxDualExtendRawPoint*)data->data;
}
else if (data->data_type == kDualExtendSpherical) {
LivoxDualExtendSpherPoint* p_point_data = (LivoxDualExtendSpherPoint*)data->data;
}
else if (data->data_type == kImu) {
LivoxImuPoint* p_point_data = (LivoxImuPoint*)data->data;
}
else if (data->data_type == kTripleExtendCartesian) {
LivoxTripleExtendRawPoint* p_point_data = (LivoxTripleExtendRawPoint*)data->data;
}
else if (data->data_type == kTripleExtendSpherical) {
LivoxTripleExtendSpherPoint* p_point_data = (LivoxTripleExtendSpherPoint*)data->data;
}
// printf("data_type %d\n", data->data_type);
}
}
static void OnSampleCallback(livox_status status, uint8_t handle, uint8_t response, void* data) {
if (status == kStatusSuccess && response != 0) {
devices[handle].device_state = kDeviceStateConnect;
}
else if (status == kStatusTimeout) {
devices[handle].device_state = kDeviceStateConnect;
}
}
static void OnStopSampleCallback(livox_status status, uint8_t handle, uint8_t response, void* data) {
// 停止采样时的回调处理
}
/** Query the firmware version of Livox LiDAR. */
static void OnDeviceInformation(livox_status status, uint8_t handle, DeviceInformationResponse* ack, void* data) {
if (status != kStatusSuccess) {
printf("Device Query Informations Failed %d\n", status);
}
if (ack) {
printf("firm ver: %d.%d.%d.%d\n",
ack->firmware_version[0],
ack->firmware_version[1],
ack->firmware_version[2],
ack->firmware_version[3]);
}
}
static void LidarConnect(const DeviceInfo* info) {
uint8_t handle = info->handle;
QueryDeviceInformation(handle, OnDeviceInformation, NULL);
if (devices[handle].device_state == kDeviceStateDisconnect) {
devices[handle].device_state = kDeviceStateConnect;
devices[handle].info = *info;
}
}
static void LidarDisConnect(const DeviceInfo* info) {
uint8_t handle = info->handle;
devices[handle].device_state = kDeviceStateDisconnect;
}
static void LidarStateChange(const DeviceInfo* info) {
uint8_t handle = info->handle;
devices[handle].info = *info;
}
static void OnDeviceInfoChange(const DeviceInfo* info, DeviceEvent type) {
if (info == NULL) {
return;
}
uint8_t handle = info->handle;
if (handle >= kMaxLidarCount) {
return;
}
if (type == kEventConnect) {
LidarConnect(info);
printf("[WARNING] Lidar sn: [%s] Connect!!!\n", info->broadcast_code);
}
else if (type == kEventDisconnect) {
LidarDisConnect(info);
printf("[WARNING] Lidar sn: [%s] Disconnect!!!\n", info->broadcast_code);
}
else if (type == kEventStateChange) {
LidarStateChange(info);
printf("[WARNING] Lidar sn: [%s] StateChange!!!\n", info->broadcast_code);
}
printf("Device Working State %d\n", devices[handle].info.state);
if (devices[handle].device_state == kDeviceStateConnect) {
if (devices[handle].info.state == kLidarStateInit) {
printf("Device State Change Progress %u\n", devices[handle].info.status.progress);
}
else {
printf("Device State Error Code 0X%08x\n", devices[handle].info.status.status_code.error_code);
}
printf("Device feature %d\n", devices[handle].info.feature);
SetErrorMessageCallback(handle, OnLidarErrorStatusCallback);
if (devices[handle].info.state == kLidarStateNormal) {
LidarStartSampling(handle, OnSampleCallback, NULL);
devices[handle].device_state = kDeviceStateSampling;
}
}
//if (python_device_change_callback) {
// python_device_change_callback(info, type);
//}
}
static void OnDeviceBroadcast(const BroadcastDeviceInfo* info) {
//if (python_device_broadcast_callback) {
// python_device_broadcast_callback(info);
//}
printf("connect to device %d \n", info->broadcast_code);
connect(info->broadcast_code);
}
CLidarHelper* CLidarHelper::Get()
{
if (CLidarHelper::m_instance == nullptr) {
CLidarHelper::m_instance = new CLidarHelper();
// 待优化
}
return CLidarHelper::m_instance;
}
CLidarHelper::CLidarHelper()
{
}
CLidarHelper::~CLidarHelper()
{
}
int CLidarHelper::Init(void* pfunGetdate)
{
pfuncGetLidarData = (FuncGetLidarData)pfunGetdate;
bool succ = init_sdk();
if (!succ)
return LIDAR_INIT_SDK_FAILED;
succ = start_discovery();
if (!succ)
return LIDAR_START_DISCOVERY_FAILD;
return LIDAR_OK;
}
int CLidarHelper::Start(int epx_time)
{
int ret = start_sampling(0);
if (ret != 0)
{
printf("start_sampling error is %d \n", ret);
return LIDAR_START_SAMPLING_FAILD;
}
return LIDAR_OK;
}
int CLidarHelper::Stop()
{
int ret = stop_sampling(0);
if (ret != 0)
{
printf("stop_sampling error is %d \n", ret);
return LIDAR_STOP_SAMPLING_FAILD;
}
return LIDAR_OK;
}
int CLidarHelper::Cap()
{
return LIDAR_OK;
}
} // extern "C"
#else
#include "LidarHelper.h"
CLidarHelper* CLidarHelper::m_instance;
#endif //_WIN32