lds_lidar.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. //
  2. // The MIT License (MIT)
  3. //
  4. // Copyright (c) 2019 Livox. All rights reserved.
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. // SOFTWARE.
  23. //
  24. #include "lds_lidar.h"
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <thread>
  28. #include <memory>
  29. namespace livox
  30. {
  31. /** Const varible ------------------------------------------------------------------------------- */
  32. /** User add broadcast code here */
  33. LidarDevice lidars_[kMaxLidarCount];
  34. bool is_initialized_=false;
  35. bool is_created=false;
  36. thread_safe_map<std::string,LdsLidar*> g_snPtr;
  37. static const char *local_broadcast_code_list[] = {
  38. "000000000000001",
  39. };
  40. /** Lds lidar function ---------------------------------------------------------------------------*/
  41. LdsLidar::LdsLidar()
  42. {
  43. if(is_created==false)
  44. {
  45. auto_connect_mode_ = true;
  46. whitelist_count_ = 0;
  47. is_initialized_ = false;
  48. lidar_count_ = 0;
  49. memset(broadcast_code_whitelist_, 0, sizeof(broadcast_code_whitelist_));
  50. memset(lidars_, 0, sizeof(lidars_));
  51. for (uint32_t i = 0; i < kMaxLidarCount; i++)
  52. {
  53. lidars_[i].handle = kMaxLidarCount;
  54. /** Unallocated state */
  55. lidars_[i].connect_state = kConnectStateOff;
  56. }
  57. is_created=true;
  58. }
  59. }
  60. LdsLidar::~LdsLidar()
  61. {
  62. }
  63. int LdsLidar::AddBroadcastCode(std::string sn)
  64. {
  65. if(g_snPtr.find(sn)==true)
  66. {
  67. printf(" %s has added \n",sn.c_str());
  68. return -1;
  69. }
  70. g_snPtr[sn]=this;
  71. return 0;
  72. }
  73. void LdsLidar::LidarDataCallback(uint8_t handle, LivoxEthPacket *data,uint32_t data_num)
  74. {
  75. printf("data recieved ------------------------------------ \n");
  76. }
  77. int LdsLidar::InitLdsLidar()
  78. {
  79. if (is_initialized_==false)
  80. {
  81. if (!Init())
  82. {
  83. Uninit();
  84. printf("Livox-SDK init fail!\n");
  85. return -1;
  86. }
  87. LivoxSdkVersion _sdkversion;
  88. GetLivoxSdkVersion(&_sdkversion);
  89. printf("Livox SDK version %d.%d.%d\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
  90. }
  91. SetBroadcastCallback(LdsLidar::OnDeviceBroadcast);
  92. SetDeviceStateUpdateCallback(LdsLidar::OnDeviceChange);
  93. /** Add commandline input broadcast code */
  94. /*for (auto input_str : broadcast_code_strs)
  95. {
  96. LdsLidar::AddBroadcastCodeToWhitelist(input_str.c_str());
  97. }*/
  98. /** Add local broadcast code */
  99. /*LdsLidar::AddLocalBroadcastCode();
  100. if (whitelist_count_)
  101. {
  102. LdsLidar::DisableAutoConnectMode();
  103. printf("Disable auto connect mode!\n");
  104. printf("List all broadcast code in whiltelist:\n");
  105. for (uint32_t i = 0; i < whitelist_count_; i++)
  106. {
  107. printf("%s\n", broadcast_code_whitelist_[i]);
  108. }
  109. }
  110. else
  111. {
  112. LdsLidar::EnableAutoConnectMode();
  113. printf("No broadcast code was added to whitelist, swith to automatic connection mode!\n");
  114. }*/
  115. /** Start livox sdk to receive lidar data */
  116. if (!Start())
  117. {
  118. Uninit();
  119. printf("Livox-SDK init fail!\n");
  120. return -1;
  121. }
  122. printf(" start -----------\n");
  123. /** Add here, only for callback use */
  124. is_initialized_ = true;
  125. printf("Livox-SDK init success!\n");
  126. return 0;
  127. }
  128. int LdsLidar::DeInitLdsLidar(void)
  129. {
  130. if (!is_initialized_)
  131. {
  132. printf("LiDAR data source is not exit");
  133. return -1;
  134. }
  135. Uninit();
  136. printf("Livox SDK Deinit completely!\n");
  137. return 0;
  138. }
  139. /** Static function in LdsLidar for callback or event process ------------------------------------*/
  140. /** Receiving point cloud data from Livox LiDAR. */
  141. void LdsLidar::GetLidarDataCb(uint8_t handle, LivoxEthPacket *data,
  142. uint32_t data_num, void *client_data)
  143. {
  144. using namespace std;
  145. LdsLidar *lidar_this = static_cast<LdsLidar *>(client_data);
  146. //printf("receive handle %d ptr %p\n", handle,client_data);
  147. if(lidar_this!= nullptr)
  148. lidar_this->LidarDataCallback(handle,data,data_num);
  149. /*LivoxEthPacket *eth_packet = data;
  150. if (!data || !data_num || (handle >= kMaxLidarCount))
  151. {
  152. return;
  153. }
  154. if (eth_packet)
  155. {
  156. lidar_this->data_recveive_count_[handle]++;
  157. if (lidar_this->data_recveive_count_[handle] % 100 == 0)
  158. {
  159. printf("receive packet count %d %d\n", handle, lidar_this->data_recveive_count_[handle]);
  160. uint64_t cur_timestamp = *((uint64_t *) (data->timestamp));
  161. if (data->data_type == kCartesian)
  162. {
  163. printf("1\n");
  164. LivoxRawPoint *p_point_data = (LivoxRawPoint *) data->data;
  165. }
  166. else if (data->data_type == kSpherical)
  167. {
  168. LivoxSpherPoint *p_point_data = (LivoxSpherPoint *) data->data;
  169. printf("2\n");
  170. }
  171. else if (data->data_type == kExtendCartesian)
  172. {
  173. LivoxExtendRawPoint *p_point_data = (LivoxExtendRawPoint *) data->data;
  174. }
  175. else if (data->data_type == kExtendSpherical)
  176. {
  177. printf("4\n");
  178. LivoxExtendSpherPoint *p_point_data = (LivoxExtendSpherPoint *) data->data;
  179. }
  180. else if (data->data_type == kDualExtendCartesian)
  181. {
  182. LivoxDualExtendRawPoint *p_point_data = (LivoxDualExtendRawPoint *) data->data;
  183. }
  184. else if (data->data_type == kDualExtendSpherical)
  185. {
  186. LivoxDualExtendSpherPoint *p_point_data = (LivoxDualExtendSpherPoint *) data->data;
  187. }
  188. else if (data->data_type == kImu)
  189. {
  190. LivoxImuPoint *p_point_data = (LivoxImuPoint *) data->data;
  191. }
  192. else if (data->data_type == kTripleExtendCartesian)
  193. {
  194. LivoxTripleExtendRawPoint *p_point_data = (LivoxTripleExtendRawPoint *) data->data;
  195. }
  196. else if (data->data_type == kTripleExtendSpherical)
  197. {
  198. LivoxTripleExtendSpherPoint *p_point_data = (LivoxTripleExtendSpherPoint *) data->data;
  199. }
  200. }
  201. }*/
  202. }
  203. void LdsLidar::OnDeviceBroadcast(const BroadcastDeviceInfo *info)
  204. {
  205. if (info == nullptr)
  206. {
  207. return;
  208. }
  209. if (info->dev_type == kDeviceTypeHub)
  210. {
  211. printf("In lidar mode, couldn't connect a hub : %s\n", info->broadcast_code);
  212. return;
  213. }
  214. /*if(g_snPtr.find(std::string(info->broadcast_code))==false)
  215. {
  216. printf("sn:%s has not added map size:%d\n",info->broadcast_code,g_snPtr.size());
  217. return;
  218. }*/
  219. if(!g_snPtr.find(info->broadcast_code))
  220. {
  221. printf(" can not find sn:%s in map\n",info->broadcast_code);
  222. return;
  223. }
  224. livox_status result = kStatusFailure;
  225. uint8_t handle = 0;
  226. result = AddLidarToConnect(info->broadcast_code, &handle);
  227. if (result == kStatusSuccess && handle < kMaxLidarCount)
  228. {
  229. LdsLidar *lidar = g_snPtr[info->broadcast_code];
  230. SetDataCallback(handle, LdsLidar::GetLidarDataCb, (void *) lidar);
  231. LidarDevice *p_lidar = &(lidars_[handle]);
  232. p_lidar->handle = handle;
  233. p_lidar->connect_state = kConnectStateOff;
  234. p_lidar->config.enable_fan = true;
  235. p_lidar->config.return_mode = kStrongestReturn;
  236. p_lidar->config.coordinate = kCoordinateCartesian;
  237. p_lidar->config.imu_rate = kImuFreq200Hz;
  238. }
  239. else
  240. {
  241. printf("Add lidar to connect is failed : %d %d \n", result, handle);
  242. }
  243. }
  244. /** Callback function of changing of device state. */
  245. void LdsLidar::OnDeviceChange(const DeviceInfo *info, DeviceEvent type)
  246. {
  247. if (info == nullptr)
  248. {
  249. return;
  250. }
  251. uint8_t handle = info->handle;
  252. if (handle >= kMaxLidarCount)
  253. {
  254. return;
  255. }
  256. if(g_snPtr.find(info->broadcast_code)==false)
  257. return;
  258. LdsLidar* ptr=g_snPtr[info->broadcast_code];
  259. LidarDevice *p_lidar = &(lidars_[handle]);
  260. if (type == kEventConnect)
  261. {
  262. QueryDeviceInformation(handle, DeviceInformationCb, ptr);
  263. if (p_lidar->connect_state == kConnectStateOff)
  264. {
  265. p_lidar->connect_state = kConnectStateOn;
  266. p_lidar->info = *info;
  267. }
  268. printf("[WARNING] Lidar sn: [%s] Connect!!!\n", info->broadcast_code);
  269. }
  270. else if (type == kEventDisconnect)
  271. {
  272. p_lidar->connect_state = kConnectStateOff;
  273. printf("[WARNING] Lidar sn: [%s] Disconnect!!!\n", info->broadcast_code);
  274. }
  275. else if (type == kEventStateChange)
  276. {
  277. p_lidar->info = *info;
  278. printf("[WARNING] Lidar sn: [%s] StateChange!!!\n", info->broadcast_code);
  279. }
  280. if (p_lidar->connect_state == kConnectStateOn)
  281. {
  282. printf("Device Working State %d\n", p_lidar->info.state);
  283. if (p_lidar->info.state == kLidarStateInit)
  284. {
  285. printf("Device State Change Progress %u\n", p_lidar->info.status.progress);
  286. }
  287. else
  288. {
  289. printf("Device State Error Code 0X%08x\n", p_lidar->info.status.status_code.error_code);
  290. }
  291. printf("Device feature %d\n", p_lidar->info.feature);
  292. SetErrorMessageCallback(handle, LdsLidar::LidarErrorStatusCb);
  293. if (p_lidar->info.state == kLidarStateNormal)
  294. {
  295. if (p_lidar->config.coordinate != 0)
  296. {
  297. SetSphericalCoordinate(handle, LdsLidar::SetCoordinateCb, ptr);
  298. }
  299. else
  300. {
  301. SetCartesianCoordinate(handle, LdsLidar::SetCoordinateCb, ptr);
  302. }
  303. p_lidar->config.set_bits |= kConfigCoordinate;
  304. if (kDeviceTypeLidarMid40 != info->type)
  305. {
  306. LidarSetPointCloudReturnMode(handle, (PointCloudReturnMode) (p_lidar->config.return_mode), \
  307. LdsLidar::SetPointCloudReturnModeCb, ptr);
  308. p_lidar->config.set_bits |= kConfigReturnMode;
  309. }
  310. if (kDeviceTypeLidarMid40 != info->type && kDeviceTypeLidarMid70 != info->type)
  311. {
  312. LidarSetImuPushFrequency(handle, (ImuFreq) (p_lidar->config.imu_rate), \
  313. LdsLidar::SetImuRatePushFrequencyCb, ptr);
  314. p_lidar->config.set_bits |= kConfigImuRate;
  315. }
  316. p_lidar->connect_state = kConnectStateConfig;
  317. }
  318. }
  319. }
  320. /** Query the firmware version of Livox LiDAR. */
  321. void LdsLidar::DeviceInformationCb(livox_status status, uint8_t handle, \
  322. DeviceInformationResponse *ack, void *client_data)
  323. {
  324. if (status != kStatusSuccess)
  325. {
  326. printf("Device Query Informations Failed : %d\n", status);
  327. }
  328. if (ack)
  329. {
  330. printf("firm ver: %d.%d.%d.%d\n",
  331. ack->firmware_version[0],
  332. ack->firmware_version[1],
  333. ack->firmware_version[2],
  334. ack->firmware_version[3]);
  335. }
  336. }
  337. /** Callback function of Lidar error message. */
  338. void LdsLidar::LidarErrorStatusCb(livox_status status, uint8_t handle, ErrorMessage *message)
  339. {
  340. static uint32_t error_message_count = 0;
  341. if (message != NULL)
  342. {
  343. ++error_message_count;
  344. if (0 == (error_message_count % 100))
  345. {
  346. printf("handle: %u\n", handle);
  347. printf("temp_status : %u\n", message->lidar_error_code.temp_status);
  348. printf("volt_status : %u\n", message->lidar_error_code.volt_status);
  349. printf("motor_status : %u\n", message->lidar_error_code.motor_status);
  350. printf("dirty_warn : %u\n", message->lidar_error_code.dirty_warn);
  351. printf("firmware_err : %u\n", message->lidar_error_code.firmware_err);
  352. printf("pps_status : %u\n", message->lidar_error_code.device_status);
  353. printf("fan_status : %u\n", message->lidar_error_code.fan_status);
  354. printf("self_heating : %u\n", message->lidar_error_code.self_heating);
  355. printf("ptp_status : %u\n", message->lidar_error_code.ptp_status);
  356. printf("time_sync_status : %u\n", message->lidar_error_code.time_sync_status);
  357. printf("system_status : %u\n", message->lidar_error_code.system_status);
  358. }
  359. }
  360. }
  361. void LdsLidar::ControlFanCb(livox_status status, uint8_t handle, \
  362. uint8_t response, void *client_data)
  363. {
  364. }
  365. void LdsLidar::SetPointCloudReturnModeCb(livox_status status, uint8_t handle, \
  366. uint8_t response, void *client_data)
  367. {
  368. LdsLidar *lds_lidar = static_cast<LdsLidar *>(client_data);
  369. if (handle >= kMaxLidarCount)
  370. {
  371. return;
  372. }
  373. LidarDevice *p_lidar = &(lidars_[handle]);
  374. if (status == kStatusSuccess)
  375. {
  376. p_lidar->config.set_bits &= ~((uint32_t) (kConfigReturnMode));
  377. printf("Set return mode success!\n");
  378. if (!p_lidar->config.set_bits)
  379. {
  380. LidarStartSampling(handle, LdsLidar::StartSampleCb, lds_lidar);
  381. p_lidar->connect_state = kConnectStateSampling;
  382. }
  383. }
  384. else
  385. {
  386. LidarSetPointCloudReturnMode(handle, (PointCloudReturnMode) (p_lidar->config.return_mode), \
  387. LdsLidar::SetPointCloudReturnModeCb, lds_lidar);
  388. printf("Set return mode fail, try again!\n");
  389. }
  390. }
  391. void LdsLidar::SetCoordinateCb(livox_status status, uint8_t handle, \
  392. uint8_t response, void *client_data)
  393. {
  394. LdsLidar *lds_lidar = static_cast<LdsLidar *>(client_data);
  395. if (handle >= kMaxLidarCount)
  396. {
  397. return;
  398. }
  399. LidarDevice *p_lidar = &(lidars_[handle]);
  400. if (status == kStatusSuccess)
  401. {
  402. p_lidar->config.set_bits &= ~((uint32_t) (kConfigCoordinate));
  403. printf("Set coordinate success!\n");
  404. if (!p_lidar->config.set_bits)
  405. {
  406. LidarStartSampling(handle, LdsLidar::StartSampleCb, lds_lidar);
  407. p_lidar->connect_state = kConnectStateSampling;
  408. }
  409. }
  410. else
  411. {
  412. if (p_lidar->config.coordinate != 0)
  413. {
  414. SetSphericalCoordinate(handle, LdsLidar::SetCoordinateCb, lds_lidar);
  415. }
  416. else
  417. {
  418. SetCartesianCoordinate(handle, LdsLidar::SetCoordinateCb, lds_lidar);
  419. }
  420. printf("Set coordinate fail, try again!\n");
  421. }
  422. }
  423. void LdsLidar::SetImuRatePushFrequencyCb(livox_status status, uint8_t handle, \
  424. uint8_t response, void *client_data)
  425. {
  426. LdsLidar *lds_lidar = static_cast<LdsLidar *>(client_data);
  427. if (handle >= kMaxLidarCount)
  428. {
  429. return;
  430. }
  431. LidarDevice *p_lidar = &(lidars_[handle]);
  432. if (status == kStatusSuccess)
  433. {
  434. p_lidar->config.set_bits &= ~((uint32_t) (kConfigImuRate));
  435. printf("Set imu rate success!\n");
  436. if (!p_lidar->config.set_bits)
  437. {
  438. LidarStartSampling(handle, LdsLidar::StartSampleCb, lds_lidar);
  439. p_lidar->connect_state = kConnectStateSampling;
  440. }
  441. }
  442. else
  443. {
  444. LidarSetImuPushFrequency(handle, (ImuFreq) (p_lidar->config.imu_rate), \
  445. LdsLidar::SetImuRatePushFrequencyCb, lds_lidar);
  446. printf("Set imu rate fail, try again!\n");
  447. }
  448. }
  449. /** Callback function of starting sampling. */
  450. void LdsLidar::StartSampleCb(livox_status status, uint8_t handle, \
  451. uint8_t response, void *client_data)
  452. {
  453. LdsLidar *lds_lidar = static_cast<LdsLidar *>(client_data);
  454. if (handle >= kMaxLidarCount)
  455. {
  456. return;
  457. }
  458. LidarDevice *p_lidar = &(lidars_[handle]);
  459. if (status == kStatusSuccess)
  460. {
  461. if (response != 0)
  462. {
  463. p_lidar->connect_state = kConnectStateOn;
  464. printf("Lidar start sample fail : state[%d] handle[%d] res[%d]\n", \
  465. status, handle, response);
  466. }
  467. else
  468. {
  469. printf("Lidar start sample success\n");
  470. }
  471. }
  472. else if (status == kStatusTimeout)
  473. {
  474. p_lidar->connect_state = kConnectStateOn;
  475. printf("Lidar start sample timeout : state[%d] handle[%d] res[%d]\n", \
  476. status, handle, response);
  477. }
  478. }
  479. /** Callback function of stopping sampling. */
  480. void LdsLidar::StopSampleCb(livox_status status, uint8_t handle, \
  481. uint8_t response, void *client_data)
  482. {
  483. }
  484. /** Add broadcast code to whitelist */
  485. int LdsLidar::AddBroadcastCodeToWhitelist(const char *bd_code)
  486. {
  487. if (!bd_code || (strlen(bd_code) > kBroadcastCodeSize) || \
  488. (whitelist_count_ >= kMaxLidarCount))
  489. {
  490. return -1;
  491. }
  492. if (LdsLidar::FindInWhitelist(bd_code))
  493. {
  494. printf("%s is alrealy exist!\n", bd_code);
  495. return -1;
  496. }
  497. strcpy(broadcast_code_whitelist_[whitelist_count_], bd_code);
  498. ++whitelist_count_;
  499. return 0;
  500. }
  501. void LdsLidar::AddLocalBroadcastCode(void)
  502. {
  503. for (size_t i = 0; i < sizeof(local_broadcast_code_list) / sizeof(intptr_t); ++i)
  504. {
  505. std::string invalid_bd = "000000000";
  506. printf("Local broadcast code : %s\n", local_broadcast_code_list[i]);
  507. if ((kBroadcastCodeSize == strlen(local_broadcast_code_list[i]) + 1) && \
  508. (nullptr == strstr(local_broadcast_code_list[i], invalid_bd.c_str())))
  509. {
  510. LdsLidar::AddBroadcastCodeToWhitelist(local_broadcast_code_list[i]);
  511. }
  512. else
  513. {
  514. printf("Invalid local broadcast code : %s\n", local_broadcast_code_list[i]);
  515. }
  516. }
  517. }
  518. bool LdsLidar::FindInWhitelist(const char *bd_code)
  519. {
  520. if (!bd_code)
  521. {
  522. return false;
  523. }
  524. for (uint32_t i = 0; i < whitelist_count_; i++)
  525. {
  526. if (strncmp(bd_code, broadcast_code_whitelist_[i], kBroadcastCodeSize) == 0)
  527. {
  528. return true;
  529. }
  530. }
  531. return false;
  532. }
  533. }