feature:add C++ sample

This commit is contained in:
Livox-SDK
2019-07-31 17:09:41 +08:00
parent 4b97e69d3b
commit 28280005c1
13 changed files with 3798 additions and 11 deletions
+2
View File
@@ -11,3 +11,5 @@ add_subdirectory(sample/hub)
add_subdirectory(sample/lidar)
add_subdirectory(sample/hub_lvx_file)
add_subdirectory(sample/lidar_lvx_file)
add_subdirectory(sample_cc/hub)
add_subdirectory(sample_cc/lidar)
+2565
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.0)
set(DEMO_NAME hub_sample_cc)
add_executable(${DEMO_NAME} lds_hub.cpp main.cpp)
target_link_libraries(${DEMO_NAME}
PRIVATE
${PROJECT_NAME}_static
)
+385
View File
@@ -0,0 +1,385 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "lds_hub.h"
#include <stdio.h>
#include <string.h>
#include <thread>
#include <memory>
/** Const varible ------------------------------------------------------------------------------- */
/** User add broadcast code here */
static const char* local_broadcast_code_list[] = {
"000000000000001",
};
/** For callback use only */
static LdsHub* g_lds_hub = nullptr;
/** Global function for common use ---------------------------------------------------------------*/
/** Lds hub function -----------------------------------------------------------------------------*/
LdsHub::LdsHub() {
auto_connect_mode_ = true;
whitelist_count_ = 0;
is_initialized_ = false;
lidar_count_ = 0;
memset(broadcast_code_whitelist_, 0, sizeof(broadcast_code_whitelist_));
memset(lidars_, 0, sizeof(lidars_));
for (uint32_t i=0; i<kMaxLidarCount; i++) {
lidars_[i].handle = kMaxLidarCount; /** Unallocated state */
lidars_[i].connect_state = kConnectStateOff;
}
memset(&hub_, 0, sizeof(hub_));
hub_.handle = kMaxLidarCount;
hub_.connect_state = kConnectStateOff;
}
LdsHub::~LdsHub() {
}
int LdsHub::InitLdsHub(std::vector<std::string>& broadcast_code_strs) {
if (is_initialized_) {
printf("LiDAR data source is already inited!\n");
return -1;
}
if (!Init()) {
Uninit();
printf("Livox-SDK init fail!\n");
return -1;
}
LivoxSdkVersion _sdkversion;
GetLivoxSdkVersion(&_sdkversion);
printf("Livox SDK version %d.%d.%d\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
SetBroadcastCallback(LdsHub::OnDeviceBroadcast);
SetDeviceStateUpdateCallback(LdsHub::OnDeviceChange);
/** Add commandline input broadcast code */
for (auto input_str : broadcast_code_strs) {
LdsHub::AddBroadcastCodeToWhitelist(input_str.c_str());
printf("Cmdline input broadcast code : %s\n", input_str.c_str());
}
/** Add local broadcast code */
LdsHub::AddLocalBroadcastCode();
if (whitelist_count_) {
LdsHub::DisableAutoConnectMode();
printf("Disable auto connect mode!\n");
printf("List all broadcast code in whiltelist:\n");
for (uint32_t i=0; i<whitelist_count_; i++) {
printf("%s\n", broadcast_code_whitelist_[i]);
}
} else {
LdsHub::EnableAutoConnectMode();
printf("No broadcast code was added to whitelist, swith to automatic connection mode!\n");
}
/** Start livox sdk to receive lidar data */
if (!Start()) {
Uninit();
printf("Livox-SDK init fail!\n");
return -1;
}
/** Add here, only for callback use */
if (g_lds_hub == nullptr) {
g_lds_hub = this;
}
is_initialized_= true;
printf("Livox-SDK init success!\n");
return 0;
}
int LdsHub::DeInitLdsHub(void) {
if (!is_initialized_) {
printf("LiDAR data source is not exit");
return -1;
}
Uninit();
printf("Livox SDK Deinit completely!\n");
return 0;
}
/** Static function in LdsLidar for callback */
void LdsHub::GetLidarDataCb(uint8_t hub_handle, LivoxEthPacket *data,
uint32_t data_num, void *client_data) {
LdsHub* lds_hub = static_cast<LdsHub *>(client_data);
LivoxEthPacket* eth_packet = data;
if (!data || !data_num) {
return;
}
/** Caculate which lidar this eth packet data belong to */
uint8_t handle = HubGetLidarHandle(eth_packet->slot, eth_packet->id);
if (handle >= kMaxLidarCount) {
return;
}
if (data) {
lds_hub->receive_packet_count_++;
if (0 == (lds_hub->receive_packet_count_ % 100)) {
printf("Receive packet count %d %d\n", handle, lds_hub->receive_packet_count_);
/** Parsing the timestamp and the point cloud data. */
uint64_t cur_timestamp = *((uint64_t *)(data->timestamp));
LivoxRawPoint *p_point_data = (LivoxRawPoint *)data->data;
}
}
}
void LdsHub::OnDeviceBroadcast(const BroadcastDeviceInfo *info) {
if (info == NULL) {
return;
}
if (info->dev_type != kDeviceTypeHub) {
printf("It's not a hub : %s\n", info->broadcast_code);
return;
}
if (g_lds_hub->IsAutoConnectMode()) {
printf("In automatic connection mode, will connect %s\n", info->broadcast_code);
} else {
if (!g_lds_hub->FindInWhitelist(info->broadcast_code)) {
printf("Not in the whitelist, please add %s to if want to connect!\n",\
info->broadcast_code);
return;
}
}
LidarDevice* p_hub = &g_lds_hub->hub_;
if (p_hub->connect_state == kConnectStateOff) {
bool result = false;
uint8_t handle = 0;
result = AddHubToConnect(info->broadcast_code, &handle);
if (result == kStatusSuccess && handle < kMaxLidarCount) {
SetDataCallback(handle, LdsHub::GetLidarDataCb, (void *)g_lds_hub);
p_hub->handle = handle;
p_hub->connect_state = kConnectStateOff;
} else {
printf("Add Hub to connect is failed : %d %d \n", result, handle);
}
}
}
/** Callback function of changing of device state. */
void LdsHub::OnDeviceChange(const DeviceInfo *info, DeviceEvent type) {
if (info == NULL) {
return;
}
if (info->handle >= kMaxLidarCount) {
return;
}
LidarDevice* p_hub = &g_lds_hub->hub_;
if (type == kEventConnect) {
if (p_hub->connect_state == kConnectStateOff) {
p_hub->connect_state = kConnectStateOn;
p_hub->info = *info;
}
} else if (type == kEventDisconnect) {
p_hub->connect_state = kConnectStateOff;
printf("Hub[%s] disconnect!\n", info->broadcast_code);
} else if (type == kEventStateChange) {
p_hub->info = *info;
printf("Hub[%s] StateChange\n", info->broadcast_code);
}
if (p_hub->connect_state == kConnectStateOn) {
printf("Hub[%s] status_code[%d] working state[%d] feature[%d]\n", \
p_hub->info.broadcast_code,\
p_hub->info.status.status_code,\
p_hub->info.state,\
p_hub->info.feature);
if (p_hub->info.state == kLidarStateNormal) {
HubQueryLidarInformation(HubQueryLidarInfoCb, g_lds_hub);
}
}
}
void LdsHub::HubQueryLidarInfoCb(uint8_t status, uint8_t handle, \
HubQueryLidarInformationResponse *response,\
void *client_data) {
LdsHub* lds_hub = static_cast<LdsHub *>(client_data);
if (handle >= kMaxLidarCount) {
return;
}
if (status == kStatusSuccess) {
if (response->count) {
printf("Hub have %d lidars:\n", response->count);
for (int i = 0; i < response->count; i++) {
uint32_t index = (response->device_info_list[i].slot - 1) * 3 +\
response->device_info_list[i].id - 1;
if (index < kMaxLidarCount) {
LidarDevice* p_lidar = &lds_hub->lidars_[index];
p_lidar->handle = index;
p_lidar->info.handle = index;
p_lidar->info.slot = response->device_info_list[i].slot;
p_lidar->info.id = response->device_info_list[i].id;
p_lidar->info.type = response->device_info_list[i].dev_type;
p_lidar->connect_state = kConnectStateSampling;
strncpy(p_lidar->info.broadcast_code, \
response->device_info_list[i].broadcast_code, \
sizeof(p_lidar->info.broadcast_code));
printf("[%d]%s DeviceType[%d] Slot[%d] Ver[%d.%d.%d.%d]\n", index, \
p_lidar->info.broadcast_code,\
p_lidar->info.type, p_lidar->info.slot,\
response->device_info_list[i].version[0],\
response->device_info_list[i].version[1],\
response->device_info_list[i].version[2],\
response->device_info_list[i].version[3]);
}
}
HubStartSampling(StartSampleCb, lds_hub);
lds_hub->hub_.connect_state = kConnectStateSampling;
} else {
printf("Hub have no lidar, will not start sample!\n");
HubQueryLidarInformation(HubQueryLidarInfoCb, lds_hub);
}
} else {
printf("Device Query Informations Failed %d\n", status);
}
}
/** Callback function of starting sampling. */
void LdsHub::StartSampleCb(uint8_t status, uint8_t handle, \
uint8_t response, void *clent_data) {
LdsHub* lds_hub = static_cast<LdsHub *>(clent_data);
if (handle >= kMaxLidarCount) {
return;
}
LidarDevice* p_hub = &lds_hub->hub_;
if (status == kStatusSuccess) {
if (response != 0) {
p_hub->connect_state = kConnectStateOn;
printf("Hub start sample fail : state[%d] handle[%d] res[%d]\n", \
status, handle, response);
} else {
printf("Hub start sample success!\n");
}
} else if (status == kStatusTimeout) {
p_hub->connect_state = kConnectStateOn;
printf("Hub start sample timeout : state[%d] handle[%d] res[%d]\n", \
status, handle, response);
}
}
/** Callback function of stopping sampling. */
void LdsHub::StopSampleCb(uint8_t status, uint8_t handle, \
uint8_t response, void *clent_data) {
}
/** Add broadcast code to whitelist */
int LdsHub::AddBroadcastCodeToWhitelist(const char* broadcast_code) {
if (!broadcast_code || (strlen(broadcast_code) > kBroadcastCodeSize) || \
(whitelist_count_ >= kMaxLidarCount)) {
return -1;
}
if (LdsHub::FindInWhitelist(broadcast_code)) {
printf("%s is alrealy exist!\n", broadcast_code);
return -1;
}
strcpy(broadcast_code_whitelist_[whitelist_count_], broadcast_code);
++whitelist_count_;
return 0;
}
void LdsHub::AddLocalBroadcastCode(void) {
for (size_t i=0; i<sizeof(local_broadcast_code_list)/sizeof(intptr_t); ++i) {
std::string invalid_bd = "000000000";
printf("Local broadcast code : %s\n", local_broadcast_code_list[i]);
if ((kBroadcastCodeSize == strlen(local_broadcast_code_list[i])) && \
(nullptr == strstr(local_broadcast_code_list[i], invalid_bd.c_str()))) {
LdsHub::AddBroadcastCodeToWhitelist(local_broadcast_code_list[i]);
} else {
printf("Invalid local broadcast code : %s\n", local_broadcast_code_list[i]);
}
}
}
bool LdsHub::FindInWhitelist(const char* broadcast_code) {
if (!broadcast_code) {
return false;
}
for (uint32_t i=0; i<whitelist_count_; i++) {
if (strncmp(broadcast_code, broadcast_code_whitelist_[i], kBroadcastCodeSize) == 0) {
return true;
}
}
return false;
}
/** Get and update LiDAR info */
void LdsHub::UpdateHubLidarinfo(void) {
DeviceInfo *_lidars = (DeviceInfo *) malloc(sizeof(DeviceInfo) * kMaxLidarCount);
uint8_t count = kMaxLidarCount;
uint8_t status = GetConnectedDevices(_lidars, &count);
if (status == kStatusSuccess) {
printf("Hub have lidars : \n");
int i = 0;
for (i = 0; i < count; ++i) {
uint8_t handle = _lidars[i].handle;
if (handle < kMaxLidarCount) {
lidars_[handle].handle = handle;
lidars_[handle].info = _lidars[i];
lidars_[handle].connect_state = kConnectStateSampling;
printf("[%d] : %s\r\n", _lidars[i].handle, _lidars[i].broadcast_code);
}
}
}
if (_lidars) {
free(_lidars);
}
}
+98
View File
@@ -0,0 +1,98 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
/** Livox LiDAR data source, data from hub */
#ifndef COAT_LDS_HUB_H_
#define COAT_LDS_HUB_H_
#include <memory>
#include <vector>
#include "livox_def.h"
#include "livox_sdk.h"
typedef enum {
kConnectStateOff = 0,
kConnectStateOn = 1,
kConnectStateSampling = 2,
} LidarConnectState;
typedef struct {
uint8_t handle;
LidarConnectState connect_state;
DeviceInfo info;
} LidarDevice;
/**
* LiDAR data source, data from hub.
*/
class LdsHub {
public:
static LdsHub& GetInstance() {
static LdsHub lds_hub;
return lds_hub;
}
int InitLdsHub(std::vector<std::string>& broadcast_code_strs);
int DeInitLdsHub(void);
private:
LdsHub();
LdsHub(const LdsHub&) = delete;
~LdsHub();
LdsHub& operator=(const LdsHub&) = delete;
/** LiDAR data receive callback */
static void GetLidarDataCb(uint8_t hub_handle, LivoxEthPacket *data,\
uint32_t data_num, void *client_data);
static void OnDeviceBroadcast(const BroadcastDeviceInfo *info);
static void OnDeviceChange(const DeviceInfo *info, DeviceEvent type);
static void StartSampleCb(uint8_t status, uint8_t handle, uint8_t response, void *clent_data);
static void StopSampleCb(uint8_t status, uint8_t handle, uint8_t response, void *clent_data);
static void HubQueryLidarInfoCb(uint8_t status, uint8_t handle, \
HubQueryLidarInformationResponse *response, void *client_data);
int AddBroadcastCodeToWhitelist(const char* broadcast_code);
void AddLocalBroadcastCode(void);
bool FindInWhitelist(const char* broadcast_code);
void UpdateHubLidarinfo(void);
void EnableAutoConnectMode(void) { auto_connect_mode_ = true; }
void DisableAutoConnectMode(void) { auto_connect_mode_ = false; }
bool IsAutoConnectMode(void) { return auto_connect_mode_; }
bool auto_connect_mode_;
uint32_t whitelist_count_;
volatile bool is_initialized_;
char broadcast_code_whitelist_[kMaxLidarCount][kBroadcastCodeSize];
uint32_t lidar_count_;
LidarDevice lidars_[kMaxLidarCount];
LidarDevice hub_;
uint32_t receive_packet_count_;
};
#endif
+141
View File
@@ -0,0 +1,141 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <string.h>
#include <apr_general.h>
#include <apr_getopt.h>
#include "lds_hub.h"
/** Cmdline input broadcast code */
static std::vector<std::string> cmdline_broadcast_code;
/** Set the program options.
* You can input the registered device broadcast code and decide whether to save the log file.
*/
static int SetProgramOption(int argc, const char *argv[]) {
apr_status_t rv;
apr_pool_t *mp = NULL;
static const apr_getopt_option_t opt_option[] = {
/** Long-option, short-option, has-arg flag, description */
{ "code", 'c', 1, "Register device broadcast code" },
{ "log", 'l', 0, "Save the log file" },
{ "help", 'h', 0, "Show help" },
{ NULL, 0, 0, NULL },
};
apr_getopt_t *opt = NULL;
int optch = 0;
const char *optarg = NULL;
if (apr_initialize() != APR_SUCCESS) {
return -1;
}
if (apr_pool_create(&mp, NULL) != APR_SUCCESS) {
return -1;
}
rv = apr_getopt_init(&opt, mp, argc, argv);
if (rv != APR_SUCCESS) {
printf("Program options initialization failed.\n");
return -1;
}
/** Parse the all options based on opt_option[] */
bool is_help = false;
while ((rv = apr_getopt_long(opt, opt_option, &optch, &optarg)) == APR_SUCCESS) {
switch (optch) {
case 'c': {
printf("Register broadcast code: %s\n", optarg);
cmdline_broadcast_code.clear();
cmdline_broadcast_code.push_back(optarg);
break;
}
case 'l': {
printf("Save the log file.\n");
SaveLoggerFile();
break;
}
case 'h': {
printf(
" [-c] Register device broadcast code\n"
" [-l] Save the log file\n"
" [-h] Show help\n"
);
is_help = true;
break;
}
default: {
break;
}
}
}
if (rv != APR_EOF) {
printf("Invalid options.\n");
}
apr_pool_destroy(mp);
mp = NULL;
apr_terminate();
if (is_help)
return 1;
return 0;
}
int main(int argc, const char *argv[]) {
/** Set the program options. */
if (SetProgramOption(argc, argv)) {
return 0;
}
LdsHub& read_hub = LdsHub::GetInstance();
int ret = read_hub.InitLdsHub(cmdline_broadcast_code);
if (!ret) {
printf("Init lds hub success!\n");
} else {
printf("Init lds hub fail!\n");
}
printf("Start discovering device.\n");
#ifdef WIN32
Sleep(100000);
#else
sleep(100);
#endif
read_hub.DeInitLdsHub();
printf("Livox hub demo end!\n");
}
+8
View File
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.0)
set(DEMO_NAME lidar_sample_cc)
add_executable(${DEMO_NAME} main.cpp lds_lidar.cpp)
target_link_libraries(${DEMO_NAME}
PRIVATE
${PROJECT_NAME}_static
)
+320
View File
@@ -0,0 +1,320 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "lds_lidar.h"
#include <stdio.h>
#include <string.h>
#include <thread>
#include <memory>
/** Const varible ------------------------------------------------------------------------------- */
/** User add broadcast code here */
static const char* local_broadcast_code_list[] = {
"000000000000001",
};
/** For callback use only */
LdsLidar* g_lidars = nullptr;
/** Lds lidar function ---------------------------------------------------------------------------*/
LdsLidar::LdsLidar() {
auto_connect_mode_ = true;
whitelist_count_ = 0;
is_initialized_ = false;
lidar_count_ = 0;
memset(broadcast_code_whitelist_, 0, sizeof(broadcast_code_whitelist_));
memset(lidars_, 0, sizeof(lidars_));
for (uint32_t i=0; i<kMaxLidarCount; i++) {
lidars_[i].handle = kMaxLidarCount; /** Unallocated state */
lidars_[i].connect_state = kConnectStateOff;
}
}
LdsLidar::~LdsLidar() {
}
int LdsLidar::InitLdsLidar(std::vector<std::string>& broadcast_code_strs) {
if (is_initialized_) {
printf("LiDAR data source is already inited!\n");
return -1;
}
if (!Init()) {
Uninit();
printf("Livox-SDK init fail!\n");
return -1;
}
LivoxSdkVersion _sdkversion;
GetLivoxSdkVersion(&_sdkversion);
printf("Livox SDK version %d.%d.%d\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
SetBroadcastCallback(LdsLidar::OnDeviceBroadcast);
SetDeviceStateUpdateCallback(LdsLidar::OnDeviceChange);
/** Add commandline input broadcast code */
for (auto input_str : broadcast_code_strs) {
LdsLidar::AddBroadcastCodeToWhitelist(input_str.c_str());
}
/** Add local broadcast code */
LdsLidar::AddLocalBroadcastCode();
if (whitelist_count_) {
LdsLidar::DisableAutoConnectMode();
printf("Disable auto connect mode!\n");
printf("List all broadcast code in whiltelist:\n");
for (uint32_t i=0; i<whitelist_count_; i++) {
printf("%s\n", broadcast_code_whitelist_[i]);
}
} else {
LdsLidar::EnableAutoConnectMode();
printf("No broadcast code was added to whitelist, swith to automatic connection mode!\n");
}
/** Start livox sdk to receive lidar data */
if (!Start()) {
Uninit();
printf("Livox-SDK init fail!\n");
return -1;
}
/** Add here, only for callback use */
if (g_lidars == nullptr) {
g_lidars = this;
}
is_initialized_= true;
printf("Livox-SDK init success!\n");
return 0;
}
int LdsLidar::DeInitLdsLidar(void) {
if (!is_initialized_) {
printf("LiDAR data source is not exit");
return -1;
}
Uninit();
printf("Livox SDK Deinit completely!\n");
return 0;
}
/** Static function in LdsLidar for callback or event process ------------------------------------*/
/** Receiving point cloud data from Livox LiDAR. */
void LdsLidar::GetLidarDataCb(uint8_t handle, LivoxEthPacket *data,
uint32_t data_num, void *client_data) {
using namespace std;
LdsLidar* lidar_this = static_cast<LdsLidar *>(client_data);
LivoxEthPacket* eth_packet = data;
if (!data || !data_num || (handle >= kMaxLidarCount)) {
return;
}
if (eth_packet) {
lidar_this->data_recveive_count_[handle] += data_num;
if (lidar_this->data_recveive_count_[handle] % 10000 == 0) {
printf("receive packet count %d %d\n", handle, lidar_this->data_recveive_count_[handle]);
/** Parsing the timestamp and the point cloud data. */
uint64_t cur_timestamp = *((uint64_t *)(data->timestamp));
LivoxRawPoint *p_point_data = (LivoxRawPoint *)data->data;
}
}
}
void LdsLidar::OnDeviceBroadcast(const BroadcastDeviceInfo *info) {
if (info == nullptr) {
return;
}
if (info->dev_type == kDeviceTypeHub) {
printf("In lidar mode, couldn't connect a hub : %s\n", info->broadcast_code);
return;
}
if (g_lidars->IsAutoConnectMode()) {
printf("In automatic connection mode, will connect %s\n", info->broadcast_code);
} else {
if (!g_lidars->FindInWhitelist(info->broadcast_code)) {
printf("Not in the whitelist, please add %s to if want to connect!\n",\
info->broadcast_code);
return;
}
}
bool result = false;
uint8_t handle = 0;
result = AddLidarToConnect(info->broadcast_code, &handle);
if (result == kStatusSuccess && handle < kMaxLidarCount) {
SetDataCallback(handle, LdsLidar::GetLidarDataCb, (void *)g_lidars);
g_lidars->lidars_[handle].handle = handle;
g_lidars->lidars_[handle].connect_state = kConnectStateOff;
} else {
printf("Add lidar to connect is failed : %d %d \n", result, handle);
}
}
/** Callback function of changing of device state. */
void LdsLidar::OnDeviceChange(const DeviceInfo *info, DeviceEvent type) {
if (info == nullptr) {
return;
}
uint8_t handle = info->handle;
if (handle >= kMaxLidarCount) {
return;
}
LidarDevice* p_lidar = &(g_lidars->lidars_[handle]);
if (type == kEventConnect) {
QueryDeviceInformation(handle, DeviceInformationCb, g_lidars);
if (p_lidar->connect_state == kConnectStateOff) {
p_lidar->connect_state = kConnectStateOn;
p_lidar->info = *info;
}
} else if (type == kEventDisconnect) {
p_lidar->connect_state = kConnectStateOff;
printf("Lidar[%s] disconnect!\n", info->broadcast_code);
} else if (type == kEventStateChange) {
p_lidar->info = *info;
}
if (p_lidar->connect_state == kConnectStateOn) {
printf("Lidar[%s] status_code[%d] working state[%d] feature[%d]\n", \
p_lidar->info.broadcast_code,\
p_lidar->info.status.status_code,\
p_lidar->info.state,\
p_lidar->info.feature);
if (p_lidar->info.state == kLidarStateNormal) {
LidarStartSampling(handle, LdsLidar::StartSampleCb, g_lidars);
p_lidar->connect_state = kConnectStateSampling;
}
}
}
/** Query the firmware version of Livox LiDAR. */
void LdsLidar::DeviceInformationCb(uint8_t status, uint8_t handle, \
DeviceInformationResponse *ack, void *clent_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]);
}
}
/** Callback function of starting sampling. */
void LdsLidar::StartSampleCb(uint8_t status, uint8_t handle, \
uint8_t response, void *clent_data) {
LdsLidar* lds_lidar = static_cast<LdsLidar *>(clent_data);
if (handle >= kMaxLidarCount) {
return;
}
LidarDevice* p_lidar = &(lds_lidar->lidars_[handle]);
if (status == kStatusSuccess) {
if (response != 0) {
p_lidar->connect_state = kConnectStateOn;
printf("Lidar start sample fail : state[%d] handle[%d] res[%d]\n", \
status, handle, response);
} else {
printf("Lidar start sample success\n");
}
} else if (status == kStatusTimeout) {
p_lidar->connect_state = kConnectStateOn;
printf("Lidar start sample timeout : state[%d] handle[%d] res[%d]\n", \
status, handle, response);
}
}
/** Callback function of stopping sampling. */
void LdsLidar::StopSampleCb(uint8_t status, uint8_t handle, \
uint8_t response, void *clent_data) {
}
/** Add broadcast code to whitelist */
int LdsLidar::AddBroadcastCodeToWhitelist(const char* bd_code) {
if (!bd_code || (strlen(bd_code) > kBroadcastCodeSize) || \
(whitelist_count_ >= kMaxLidarCount)) {
return -1;
}
if (LdsLidar::FindInWhitelist(bd_code)) {
printf("%s is alrealy exist!\n", bd_code);
return -1;
}
strcpy(broadcast_code_whitelist_[whitelist_count_], bd_code);
++whitelist_count_;
return 0;
}
void LdsLidar::AddLocalBroadcastCode(void) {
for (size_t i=0; i<sizeof(local_broadcast_code_list)/sizeof(intptr_t); ++i) {
std::string invalid_bd = "000000000";
printf("Local broadcast code : %s\n", local_broadcast_code_list[i]);
if ((kBroadcastCodeSize == strlen(local_broadcast_code_list[i])) && \
(nullptr == strstr(local_broadcast_code_list[i], invalid_bd.c_str()))) {
LdsLidar::AddBroadcastCodeToWhitelist(local_broadcast_code_list[i]);
} else {
printf("Invalid local broadcast code : %s\n", local_broadcast_code_list[i]);
}
}
}
bool LdsLidar::FindInWhitelist(const char* bd_code) {
if (!bd_code) {
return false;
}
for (uint32_t i=0; i<whitelist_count_; i++) {
if (strncmp(bd_code, broadcast_code_whitelist_[i], kBroadcastCodeSize) == 0) {
return true;
}
}
return false;
}
+97
View File
@@ -0,0 +1,97 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
/** Livox LiDAR data source, data from dependent lidar */
#ifndef LDS_LIDAR_H_
#define LDS_LIDAR_H_
#include <memory>
#include <vector>
#include "livox_def.h"
#include "livox_sdk.h"
typedef enum {
kConnectStateOff = 0,
kConnectStateOn = 1,
kConnectStateSampling = 2,
} LidarConnectState;
typedef struct {
uint8_t handle;
LidarConnectState connect_state;
DeviceInfo info;
} LidarDevice;
/**
* LiDAR data source, data from dependent lidar.
*/
class LdsLidar {
public:
static LdsLidar& GetInstance() {
static LdsLidar lds_lidar;
return lds_lidar;
}
int InitLdsLidar(std::vector<std::string>& broadcast_code_strs);
int DeInitLdsLidar(void);
private:
LdsLidar();
LdsLidar(const LdsLidar&) = delete;
~LdsLidar();
LdsLidar& operator=(const LdsLidar&) = delete;
static void GetLidarDataCb(uint8_t handle, LivoxEthPacket *data,\
uint32_t data_num, void *client_data);
static void OnDeviceBroadcast(const BroadcastDeviceInfo *info);
static void OnDeviceChange(const DeviceInfo *info, DeviceEvent type);
static void StartSampleCb(uint8_t status, uint8_t handle, uint8_t response, void *clent_data);
static void StopSampleCb(uint8_t status, uint8_t handle, uint8_t response, void *clent_data);
static void DeviceInformationCb(uint8_t status, uint8_t handle, \
DeviceInformationResponse *ack, void *clent_data);
int AddBroadcastCodeToWhitelist(const char* broadcast_code);
void AddLocalBroadcastCode(void);
bool FindInWhitelist(const char* broadcast_code);
void EnableAutoConnectMode(void) { auto_connect_mode_ = true; }
void DisableAutoConnectMode(void) { auto_connect_mode_ = false; }
bool IsAutoConnectMode(void) { return auto_connect_mode_; }
bool auto_connect_mode_;
uint32_t whitelist_count_;
volatile bool is_initialized_;
char broadcast_code_whitelist_[kMaxLidarCount][kBroadcastCodeSize];
uint32_t lidar_count_;
LidarDevice lidars_[kMaxLidarCount];
uint32_t data_recveive_count_[kMaxLidarCount];
};
#endif
+151
View File
@@ -0,0 +1,151 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <string.h>
#include <apr_general.h>
#include <apr_getopt.h>
#include "lds_lidar.h"
/** Cmdline input broadcast code */
static std::vector<std::string> cmdline_broadcast_code;
/** Set the program options.
* You can input the registered device broadcast code and decide whether to save the log file.
*/
static int SetProgramOption(int argc, const char *argv[]) {
apr_status_t rv;
apr_pool_t *mp = NULL;
static const apr_getopt_option_t opt_option[] = {
/** Long-option, short-option, has-arg flag, description */
{ "code", 'c', 1, "Register device broadcast code" },
{ "log", 'l', 0, "Save the log file" },
{ "help", 'h', 0, "Show help" },
{ NULL, 0, 0, NULL },
};
apr_getopt_t *opt = NULL;
int optch = 0;
const char *optarg = NULL;
if (apr_initialize() != APR_SUCCESS) {
return -1;
}
if (apr_pool_create(&mp, NULL) != APR_SUCCESS) {
return -1;
}
rv = apr_getopt_init(&opt, mp, argc, argv);
if (rv != APR_SUCCESS) {
printf("Program options initialization failed.\n");
return -1;
}
/** Parse the all options based on opt_option[] */
bool is_help = false;
while ((rv = apr_getopt_long(opt, opt_option, &optch, &optarg)) == APR_SUCCESS) {
switch (optch) {
case 'c': {
printf("Register broadcast code: %s\n", optarg);
char *sn_list = (char *)malloc(sizeof(char)*(strlen(optarg) + 1));
strncpy(sn_list, optarg, sizeof(char)*(strlen(optarg) + 1));
char *sn_list_head = sn_list;
sn_list = strtok(sn_list, "&");
cmdline_broadcast_code.clear();
while (sn_list) {
cmdline_broadcast_code.push_back(sn_list);
sn_list = strtok(nullptr, "&");
}
free(sn_list_head);
sn_list_head = nullptr;
break;
}
case 'l': {
printf("Save the log file.\n");
SaveLoggerFile();
break;
}
case 'h': {
printf(
" [-c] Register device broadcast code\n"
" [-l] Save the log file\n"
" [-h] Show help\n"
);
is_help = true;
break;
}
default: {
break;
}
}
}
if (rv != APR_EOF) {
printf("Invalid options.\n");
}
apr_pool_destroy(mp);
mp = NULL;
apr_terminate();
if (is_help)
return 1;
return 0;
}
int main(int argc, const char *argv[]) {
/** Set the program options. */
if (SetProgramOption(argc, argv)) {
return 0;
}
LdsLidar& read_lidar = LdsLidar::GetInstance();
int ret = read_lidar.InitLdsLidar(cmdline_broadcast_code);
if (!ret) {
printf("Init lds lidar success!\n");
} else {
printf("Init lds lidar fail!\n");
}
printf("Start discovering device.\n");
#ifdef WIN32
Sleep(100000);
#else
sleep(100);
#endif
read_lidar.DeInitLdsLidar();
printf("Livox lidar demo end!\n");
}
+2 -1
View File
@@ -108,4 +108,5 @@ target_sources(${SDK_LIBRARY}
install(TARGETS ${SDK_LIBRARY}
PUBLIC_HEADER DESTINATION include
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
LIBRARY DESTINATION lib)
+6
View File
@@ -28,6 +28,12 @@ std::shared_ptr<spdlog::logger> logger = NULL;
bool is_save_log_file = false;
void InitLogger() {
if (spdlog::get("console") != nullptr) {
logger = spdlog::get("console");
return;
}
std::vector<spdlog::sink_ptr> sinkList;
auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
consoleSink->set_level(spdlog::level::debug);
+15 -10
View File
@@ -110,15 +110,19 @@ void DeviceManager::UpdateDevices(const DeviceInfo &device, DeviceEvent type) {
connected_cb_(&device, type);
}
if ((device_mode_ == kDeviceModeHub) && (type == kEventConnect)) {
LOG_DEBUG("Send Query lidars command");
command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubQueryLidarInformation,
NULL,
0,
MakeCommandCallback<DeviceManager, HubQueryLidarInformationResponse>(
this, &DeviceManager::HubLidarInfomationCallback));
if (device_mode_ == kDeviceModeHub) {
if (type == kEventConnect) {
LOG_DEBUG("Send Query lidars command");
command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubQueryLidarInformation,
NULL,
0,
MakeCommandCallback<DeviceManager, HubQueryLidarInformationResponse>(
this, &DeviceManager::HubLidarInfomationCallback));
} else if (connected_cb_) {
connected_cb_(&device, type);
}
}
}
@@ -227,7 +231,8 @@ void DeviceManager::UpdateDeviceState(uint8_t handle, const HeartbeatResponse &r
update = true;
}
if (info.status.progress != response.error_union.progress) {
LOG_INFO(" Update progress {}, device connect {}", (uint16_t)response.error_union.progress, devices_[handle].connected);
LOG_INFO(
" Update progress {}, device connect {}", (uint16_t)response.error_union.progress, devices_[handle].connected);
info.status.progress = response.error_union.progress;
update = true;
}