#ifndef _WIN32 #include #include #ifndef _WIN32 #include #endif #include #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